merge application.js
11
Gemfile
|
@ -1,4 +1,5 @@
|
||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
|
#ruby '1.9.3'
|
||||||
|
|
||||||
gem 'rails', '3.2.17'
|
gem 'rails', '3.2.17'
|
||||||
|
|
||||||
|
@ -6,7 +7,7 @@ gem 'rails', '3.2.17'
|
||||||
# gem 'rails', :git => 'git://github.com/rails/rails.git'
|
# gem 'rails', :git => 'git://github.com/rails/rails.git'
|
||||||
|
|
||||||
gem 'devise'
|
gem 'devise'
|
||||||
gem 'redis'
|
gem 'redis', '2.2.2'
|
||||||
gem 'pg'
|
gem 'pg'
|
||||||
gem 'cancan'
|
gem 'cancan'
|
||||||
gem 'formula'
|
gem 'formula'
|
||||||
|
@ -14,6 +15,10 @@ gem 'formtastic'
|
||||||
gem 'json'
|
gem 'json'
|
||||||
gem 'rails3-jquery-autocomplete'
|
gem 'rails3-jquery-autocomplete'
|
||||||
gem 'best_in_place'
|
gem 'best_in_place'
|
||||||
|
|
||||||
|
gem 'paperclip'
|
||||||
|
gem 'aws-sdk'
|
||||||
|
|
||||||
#gem 'therubyracer' #optional
|
#gem 'therubyracer' #optional
|
||||||
#gem 'rb-readline'
|
#gem 'rb-readline'
|
||||||
|
|
||||||
|
@ -29,6 +34,10 @@ group :assets do
|
||||||
gem 'uglifier', '>= 1.0.3'
|
gem 'uglifier', '>= 1.0.3'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
group :production do #this is used on heroku
|
||||||
|
#gem 'rmagick'
|
||||||
|
end
|
||||||
|
|
||||||
gem 'jquery-rails', '2.1.2'
|
gem 'jquery-rails', '2.1.2'
|
||||||
|
|
||||||
# To use ActiveModel has_secure_password
|
# To use ActiveModel has_secure_password
|
||||||
|
|
23
Gemfile.lock
|
@ -29,6 +29,9 @@ GEM
|
||||||
i18n (~> 0.6, >= 0.6.4)
|
i18n (~> 0.6, >= 0.6.4)
|
||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
arel (3.0.3)
|
arel (3.0.3)
|
||||||
|
aws-sdk (1.44.0)
|
||||||
|
json (~> 1.4)
|
||||||
|
nokogiri (>= 1.4.4)
|
||||||
bcrypt (3.1.7)
|
bcrypt (3.1.7)
|
||||||
bcrypt (3.1.7-x86-mingw32)
|
bcrypt (3.1.7-x86-mingw32)
|
||||||
best_in_place (2.1.0)
|
best_in_place (2.1.0)
|
||||||
|
@ -36,6 +39,10 @@ GEM
|
||||||
rails (~> 3.1)
|
rails (~> 3.1)
|
||||||
builder (3.0.4)
|
builder (3.0.4)
|
||||||
cancan (1.6.10)
|
cancan (1.6.10)
|
||||||
|
climate_control (0.0.3)
|
||||||
|
activesupport (>= 3.0)
|
||||||
|
cocaine (0.5.4)
|
||||||
|
climate_control (>= 0.0.3, < 1.0)
|
||||||
coffee-rails (3.2.2)
|
coffee-rails (3.2.2)
|
||||||
coffee-script (>= 2.2.0)
|
coffee-script (>= 2.2.0)
|
||||||
railties (~> 3.2.0)
|
railties (~> 3.2.0)
|
||||||
|
@ -68,8 +75,18 @@ GEM
|
||||||
mime-types (~> 1.16)
|
mime-types (~> 1.16)
|
||||||
treetop (~> 1.4.8)
|
treetop (~> 1.4.8)
|
||||||
mime-types (1.25.1)
|
mime-types (1.25.1)
|
||||||
|
mini_portile (0.6.0)
|
||||||
multi_json (1.10.0)
|
multi_json (1.10.0)
|
||||||
|
nokogiri (1.6.2.1)
|
||||||
|
mini_portile (= 0.6.0)
|
||||||
|
nokogiri (1.6.2.1-x86-mingw32)
|
||||||
|
mini_portile (= 0.6.0)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
|
paperclip (4.1.1)
|
||||||
|
activemodel (>= 3.0.0)
|
||||||
|
activesupport (>= 3.0.0)
|
||||||
|
cocaine (~> 0.5.3)
|
||||||
|
mime-types
|
||||||
pg (0.17.1)
|
pg (0.17.1)
|
||||||
pg (0.17.1-x86-mingw32)
|
pg (0.17.1-x86-mingw32)
|
||||||
polyglot (0.3.4)
|
polyglot (0.3.4)
|
||||||
|
@ -100,7 +117,7 @@ GEM
|
||||||
rake (10.3.2)
|
rake (10.3.2)
|
||||||
rdoc (3.12.2)
|
rdoc (3.12.2)
|
||||||
json (~> 1.4)
|
json (~> 1.4)
|
||||||
redis (3.0.7)
|
redis (2.2.2)
|
||||||
sass (3.3.7)
|
sass (3.3.7)
|
||||||
sass-rails (3.2.6)
|
sass-rails (3.2.6)
|
||||||
railties (~> 3.2.0)
|
railties (~> 3.2.0)
|
||||||
|
@ -129,6 +146,7 @@ PLATFORMS
|
||||||
x86-mingw32
|
x86-mingw32
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
aws-sdk
|
||||||
best_in_place
|
best_in_place
|
||||||
cancan
|
cancan
|
||||||
coffee-rails (~> 3.2.1)
|
coffee-rails (~> 3.2.1)
|
||||||
|
@ -138,9 +156,10 @@ DEPENDENCIES
|
||||||
jbuilder (= 0.8.2)
|
jbuilder (= 0.8.2)
|
||||||
jquery-rails (= 2.1.2)
|
jquery-rails (= 2.1.2)
|
||||||
json
|
json
|
||||||
|
paperclip
|
||||||
pg
|
pg
|
||||||
rails (= 3.2.17)
|
rails (= 3.2.17)
|
||||||
rails3-jquery-autocomplete
|
rails3-jquery-autocomplete
|
||||||
redis
|
redis (= 2.2.2)
|
||||||
sass-rails
|
sass-rails
|
||||||
uglifier (>= 1.0.3)
|
uglifier (>= 1.0.3)
|
||||||
|
|
47
Gemfile~
|
@ -1,47 +0,0 @@
|
||||||
source 'https://rubygems.org'
|
|
||||||
|
|
||||||
gem 'rails', '3.2.17'
|
|
||||||
|
|
||||||
# Bundle edge Rails instead:
|
|
||||||
# gem 'rails', :git => 'git://github.com/rails/rails.git'
|
|
||||||
|
|
||||||
gem 'devise'
|
|
||||||
gem 'redis'
|
|
||||||
gem 'pg'
|
|
||||||
gem 'cancan'
|
|
||||||
gem 'formula'
|
|
||||||
gem 'formtastic'
|
|
||||||
gem 'json'
|
|
||||||
gem 'rails3-jquery-autocomplete'
|
|
||||||
gem 'best_in_place'
|
|
||||||
gem 'therubyracer' #optional
|
|
||||||
#gem 'rb-readline'
|
|
||||||
|
|
||||||
# Gems used only for assets and not required
|
|
||||||
# in production environments by default.
|
|
||||||
group :assets do
|
|
||||||
gem 'sass-rails'
|
|
||||||
gem 'coffee-rails', '~> 3.2.1'
|
|
||||||
|
|
||||||
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
|
|
||||||
# gem 'therubyracer'
|
|
||||||
|
|
||||||
gem 'uglifier', '>= 1.0.3'
|
|
||||||
end
|
|
||||||
|
|
||||||
gem 'jquery-rails', '2.1.2'
|
|
||||||
|
|
||||||
# To use ActiveModel has_secure_password
|
|
||||||
# gem 'bcrypt-ruby', '~> 3.0.0'
|
|
||||||
|
|
||||||
# To use Jbuilder templates for JSON
|
|
||||||
gem 'jbuilder', '0.8.2'
|
|
||||||
|
|
||||||
# Use unicorn as the web server
|
|
||||||
# gem 'unicorn'
|
|
||||||
|
|
||||||
# Deploy with Capistrano
|
|
||||||
# gem 'capistrano'
|
|
||||||
|
|
||||||
# To use debugger
|
|
||||||
# gem 'ruby-debug19', :require => 'ruby-debug'
|
|
2
Rakefile
|
@ -4,4 +4,4 @@
|
||||||
|
|
||||||
require File.expand_path('../config/application', __FILE__)
|
require File.expand_path('../config/application', __FILE__)
|
||||||
|
|
||||||
ISSAD::Application.load_tasks
|
Metamaps::Application.load_tasks
|
||||||
|
|
BIN
app/assets/images/synapsevisualize.png
Normal file
After Width: | Height: | Size: 909 B |
|
@ -1,183 +0,0 @@
|
||||||
// create filters for maps
|
|
||||||
|
|
||||||
function switchVisible(category, duration) {
|
|
||||||
if (categoryVisible[category] == true) {
|
|
||||||
hideCategory(category, duration);
|
|
||||||
}
|
|
||||||
else if (categoryVisible[category] == false) {
|
|
||||||
showCategory(category, duration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideCategory(category, duration) {
|
|
||||||
if (duration == null) duration = 500;
|
|
||||||
Mconsole.graph.eachNode( function (n) {
|
|
||||||
if (n.getData('metacode') == category) {
|
|
||||||
n.setData('alpha', 0.4, 'end');
|
|
||||||
n.eachAdjacency(function(adj) {
|
|
||||||
adj.setData('alpha', 0.4, 'end');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['node-property:alpha',
|
|
||||||
'edge-property:alpha'],
|
|
||||||
duration: duration
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showCategory(category, duration) {
|
|
||||||
if (duration == null) duration = 500;
|
|
||||||
Mconsole.graph.eachNode( function (n) {
|
|
||||||
if (n.getData('metacode') == category) {
|
|
||||||
n.setData('alpha', 1, 'end');
|
|
||||||
n.eachAdjacency(function(adj) {
|
|
||||||
adj.setData('alpha', 1, 'end');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['node-property:alpha',
|
|
||||||
'edge-property:alpha'],
|
|
||||||
duration: duration
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// These functions toggle ALL nodes and synapses on the page
|
|
||||||
function hideAll(duration) {
|
|
||||||
if (duration == null) duration = 500;
|
|
||||||
Mconsole.graph.eachNode( function (n) {
|
|
||||||
n.setData('alpha', 0.4, 'end');
|
|
||||||
n.eachAdjacency(function(adj) {
|
|
||||||
adj.setData('alpha', 0.2, 'end');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['node-property:alpha',
|
|
||||||
'edge-property:alpha'],
|
|
||||||
duration: duration
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function showAll(duration) {
|
|
||||||
if (duration == null) duration = 500;
|
|
||||||
Mconsole.graph.eachNode( function (n) {
|
|
||||||
n.setData('alpha', 1, 'end');
|
|
||||||
n.eachAdjacency(function(adj) {
|
|
||||||
adj.setData('alpha', 0.4, 'end');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['node-property:alpha',
|
|
||||||
'edge-property:alpha'],
|
|
||||||
duration: duration
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterTopicsByMap(mapID) {
|
|
||||||
Mconsole.graph.eachNode(function (n) {
|
|
||||||
if (n.getData('inmaps').indexOf(parseInt(mapID)) !== -1) {
|
|
||||||
n.setData('alpha', 1, 'end');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
n.setData('alpha', 0.4, 'end');
|
|
||||||
}
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['node-property:alpha',
|
|
||||||
'edge-property:alpha'],
|
|
||||||
duration: 500
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} // filterTopicsByName
|
|
||||||
|
|
||||||
function filterTopicsByMapper(mapperID) {
|
|
||||||
Mconsole.graph.eachNode(function (n) {
|
|
||||||
if (n.getData('userid').toString() == mapperID) {
|
|
||||||
n.setData('alpha', 1, 'end');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
n.setData('alpha', 0.4, 'end');
|
|
||||||
}
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['node-property:alpha',
|
|
||||||
'edge-property:alpha'],
|
|
||||||
duration: 500
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} // filterTopicsByName
|
|
||||||
|
|
||||||
function filterTopicsByName(searchQuery) {
|
|
||||||
Mconsole.graph.eachNode(function (n) {
|
|
||||||
nodeName = n.name.toLowerCase();
|
|
||||||
if (nodeName.indexOf(searchQuery) !== -1 && searchQuery != "") {
|
|
||||||
n.setData('alpha', 1, 'end');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
n.setData('alpha', 0.4, 'end');
|
|
||||||
}
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['node-property:alpha',
|
|
||||||
'edge-property:alpha'],
|
|
||||||
duration: 500
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} // filterTopicsByName
|
|
||||||
|
|
||||||
function clearCanvas() {
|
|
||||||
Mconsole.graph.eachNode(function(n) {
|
|
||||||
Mconsole.graph.removeNode(n.id);
|
|
||||||
});
|
|
||||||
Mconsole.plot();
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearCanvasExceptRoot() {
|
|
||||||
var ids = new Array();
|
|
||||||
Mconsole.graph.eachNode(function(n) {
|
|
||||||
ids.push(n.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
var root = Mconsole.graph.nodes[Mconsole.root];
|
|
||||||
ids.forEach(function(id, index) {
|
|
||||||
if (id != root.id) {
|
|
||||||
Mconsole.graph.removeNode(id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
fetchRelatives(root); //also runs Mconsole.plot()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define all the dynamic interactions for the Filter By Metacode using Jquery
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('.sidebarFilterBox .showAll').click(function(e) {
|
|
||||||
showAll();
|
|
||||||
$('#filter_by_metacode ul li').removeClass('toggledOff');
|
|
||||||
for (var catVis in categoryVisible) {
|
|
||||||
categoryVisible[catVis] = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$('.sidebarFilterBox .hideAll').click(function(e) {
|
|
||||||
hideAll();
|
|
||||||
$('#filter_by_metacode ul li').addClass('toggledOff');
|
|
||||||
for (var catVis in categoryVisible) {
|
|
||||||
categoryVisible[catVis] = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// toggle visibility of topics with metacodes based on status in the filters list
|
|
||||||
$('#filter_by_metacode ul li').click(function(event) {
|
|
||||||
|
|
||||||
var category = $(this).children('img').attr('alt');
|
|
||||||
switchVisible(category);
|
|
||||||
|
|
||||||
// toggle the image and the boolean array value
|
|
||||||
if (categoryVisible[category] == true) {
|
|
||||||
$(this).addClass('toggledOff');
|
|
||||||
categoryVisible[category] = false;
|
|
||||||
}
|
|
||||||
else if (categoryVisible[category] == false) {
|
|
||||||
$(this).removeClass('toggledOff');
|
|
||||||
categoryVisible[category] = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,631 +0,0 @@
|
||||||
function selectEdgeOnClickHandler(adj, e) {
|
|
||||||
if (Mconsole.busy) return;
|
|
||||||
|
|
||||||
// catch right click on mac, which is often like ctrl+click
|
|
||||||
if (navigator.platform.indexOf("Mac") != -1 && e.ctrlKey) {
|
|
||||||
selectEdgeOnRightClickHandler(adj, e)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (synapseWasDoubleClicked()) {
|
|
||||||
synapseDoubleClickHandler(adj, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var edgeIsSelected = MetamapsModel.selectedEdges.indexOf(adj);
|
|
||||||
if (edgeIsSelected == -1) edgeIsSelected = false;
|
|
||||||
else if (edgeIsSelected != -1) edgeIsSelected = true;
|
|
||||||
|
|
||||||
if (edgeIsSelected && e.shiftKey) {
|
|
||||||
//deselecting an edge with shift
|
|
||||||
deselectEdge(adj);
|
|
||||||
} else if (!edgeIsSelected && e.shiftKey) {
|
|
||||||
//selecting an edge with shift
|
|
||||||
selectEdge(adj);
|
|
||||||
} else if (edgeIsSelected && !e.shiftKey) {
|
|
||||||
//deselecting an edge without shift - unselect all
|
|
||||||
deselectAllEdges();
|
|
||||||
} else if (!edgeIsSelected && !e.shiftKey) {
|
|
||||||
//selecting an edge without shift - unselect all but new one
|
|
||||||
deselectAllEdges();
|
|
||||||
selectEdge(adj);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mconsole.plot();
|
|
||||||
} //selectEdgeOnClickHandler
|
|
||||||
|
|
||||||
function selectEdgeOnRightClickHandler(adj, e) {
|
|
||||||
// the 'node' variable is a JIT node, the one that was clicked on
|
|
||||||
// the 'e' variable is the click event
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
if (Mconsole.busy) return;
|
|
||||||
|
|
||||||
selectEdge(adj);
|
|
||||||
|
|
||||||
// delete old right click menu
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
// create new menu for clicked on node
|
|
||||||
var rightclickmenu = document.createElement("div");
|
|
||||||
rightclickmenu.className = "rightclickmenu";
|
|
||||||
|
|
||||||
// add the proper options to the menu
|
|
||||||
var menustring = '<ul>';
|
|
||||||
|
|
||||||
if (userid != null) menustring += '<li class="rc-delete">Delete</li>';
|
|
||||||
if (mapid && userid != null) menustring += '<li class="rc-remove">Remove from map</li>';
|
|
||||||
menustring += '<li class="rc-hide">Hide until refresh</li>';
|
|
||||||
if (userid) {
|
|
||||||
var options = '<ul><li class="changeP toCommons">commons</li> \
|
|
||||||
<li class="changeP toPublic">public</li> \
|
|
||||||
<li class="changeP toPrivate">private</li> \
|
|
||||||
</ul>';
|
|
||||||
|
|
||||||
menustring += '<li class="rc-permission">Change permissions' + options + '</li>';
|
|
||||||
}
|
|
||||||
|
|
||||||
menustring += '</ul>';
|
|
||||||
rightclickmenu.innerHTML = menustring;
|
|
||||||
|
|
||||||
// position the menu where the click happened
|
|
||||||
$(rightclickmenu).css({
|
|
||||||
left: e.clientX,
|
|
||||||
top: e.clientY
|
|
||||||
});
|
|
||||||
//add the menu to the page
|
|
||||||
$('#center-container').append(rightclickmenu);
|
|
||||||
|
|
||||||
|
|
||||||
// attach events to clicks on the list items
|
|
||||||
|
|
||||||
// delete the selected things from the database
|
|
||||||
$('.rc-delete').click(function () {
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
var n = MetamapsModel.selectedNodes.length;
|
|
||||||
var e = MetamapsModel.selectedEdges.length;
|
|
||||||
var ntext = n == 1 ? "1 topic" : n + " topics";
|
|
||||||
var etext = e == 1 ? "1 synapse" : e + " synapses";
|
|
||||||
var text = "You have " + ntext + " and " + etext + " selected. ";
|
|
||||||
|
|
||||||
var r = confirm(text + "Are you sure you want to permanently delete them all? This will remove them from all maps they appear on.");
|
|
||||||
if (r == true) {
|
|
||||||
deleteSelectedEdges();
|
|
||||||
deleteSelectedNodes();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// remove the selected things from the map
|
|
||||||
$('.rc-remove').click(function () {
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
removeSelectedEdges();
|
|
||||||
removeSelectedNodes();
|
|
||||||
});
|
|
||||||
|
|
||||||
// hide selected nodes and synapses until refresh
|
|
||||||
$('.rc-hide').click(function () {
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
hideSelectedEdges();
|
|
||||||
hideSelectedNodes();
|
|
||||||
});
|
|
||||||
|
|
||||||
// change the permission of all the selected nodes and synapses that you were the originator of
|
|
||||||
$('.rc-permission li').click(function () {
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
// $(this).text() will be 'commons' 'public' or 'private'
|
|
||||||
updateSelectedPermissions($(this).text());
|
|
||||||
});
|
|
||||||
|
|
||||||
} //selectEdgeOnRightClickHandler
|
|
||||||
|
|
||||||
|
|
||||||
function synapseDoubleClickHandler(adj, e) {
|
|
||||||
editEdge(adj, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns a boolean saying if the synapse was double clicked in our understanding of the word
|
|
||||||
*/
|
|
||||||
function synapseWasDoubleClicked() {
|
|
||||||
//grab the timestamp of the click
|
|
||||||
var storedTime = MetamapsModel.lastSynapseClick;
|
|
||||||
var now = Date.now(); //not compatible with IE8 FYI
|
|
||||||
MetamapsModel.lastSynapseClick = now;
|
|
||||||
|
|
||||||
if (now - storedTime < MetamapsModel.DOUBLE_CLICK_TOLERANCE) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} //synapseWasDoubleClicked;
|
|
||||||
|
|
||||||
function nodeDoubleClickHandler(node, e) {
|
|
||||||
openNodeShowcard(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
function enterKeyHandler(event) {
|
|
||||||
|
|
||||||
//var selectedNodesCopy = MetamapsModel.selectedNodes.slice(0);
|
|
||||||
//var len = selectedNodesCopy.length;
|
|
||||||
//for (var i = 0; i < len; i += 1) {
|
|
||||||
// n = selectedNodesCopy[i];
|
|
||||||
// keepFromCommons(n);
|
|
||||||
//}//for
|
|
||||||
//Mconsole.plot();
|
|
||||||
} //enterKeyHandler
|
|
||||||
|
|
||||||
function escKeyHandler() {
|
|
||||||
deselectAllEdges();
|
|
||||||
deselectAllNodes();
|
|
||||||
} //escKeyHandler
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make a node "in the commons" (with a green circle) lose its
|
|
||||||
* green circle so it stays on the console/map/...
|
|
||||||
*/
|
|
||||||
function keepFromCommons(event, id) {
|
|
||||||
if (userid == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#topic_addSynapse').val("false");
|
|
||||||
$('#topic_x').val(0);
|
|
||||||
$('#topic_y').val(0);
|
|
||||||
$('#topic_grabTopic').val(id);
|
|
||||||
$('.new_topic').submit();
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
return false;
|
|
||||||
} //doubleClickNodeHandler
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns a boolean saying if the node was double clicked in our understanding of the word
|
|
||||||
*/
|
|
||||||
function nodeWasDoubleClicked() {
|
|
||||||
//grab the timestamp of the click
|
|
||||||
var storedTime = MetamapsModel.lastNodeClick;
|
|
||||||
var now = Date.now(); //not compatible with IE8 FYI
|
|
||||||
MetamapsModel.lastNodeClick = now;
|
|
||||||
|
|
||||||
if (now - storedTime < MetamapsModel.DOUBLE_CLICK_TOLERANCE) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} //nodeWasDoubleClicked;
|
|
||||||
|
|
||||||
function selectNodeOnClickHandler(node, e) {
|
|
||||||
if (Mconsole.busy) return;
|
|
||||||
|
|
||||||
// catch right click on mac, which is often like ctrl+click
|
|
||||||
if (navigator.platform.indexOf("Mac") != -1 && e.ctrlKey) {
|
|
||||||
selectNodeOnRightClickHandler(node, e)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if on a topic page, let alt+click center you on a new topic
|
|
||||||
if (!mapid && e.altKey) {
|
|
||||||
centerOn(node.id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var check = nodeWasDoubleClicked();
|
|
||||||
if (check) {
|
|
||||||
nodeDoubleClickHandler(node, e);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// wait a certain length of time, then check again, then run this code
|
|
||||||
setTimeout(function () {
|
|
||||||
if (!nodeWasDoubleClicked()) {
|
|
||||||
if (!e.shiftKey) {
|
|
||||||
Mconsole.graph.eachNode(function (n) {
|
|
||||||
if (n.id != node.id) {
|
|
||||||
deselectNode(n);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (node.selected) {
|
|
||||||
deselectNode(node);
|
|
||||||
} else {
|
|
||||||
selectNode(node);
|
|
||||||
}
|
|
||||||
//trigger animation to final styles
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['edge-property:lineWidth:color:alpha'],
|
|
||||||
duration: 500
|
|
||||||
});
|
|
||||||
Mconsole.plot();
|
|
||||||
}
|
|
||||||
}, MetamapsModel.DOUBLE_CLICK_TOLERANCE);
|
|
||||||
}
|
|
||||||
} //selectNodeOnClickHandler
|
|
||||||
|
|
||||||
function selectNodeOnRightClickHandler(node, e) {
|
|
||||||
// the 'node' variable is a JIT node, the one that was clicked on
|
|
||||||
// the 'e' variable is the click event
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
if (Mconsole.busy) return;
|
|
||||||
|
|
||||||
selectNode(node);
|
|
||||||
|
|
||||||
// delete old right click menu
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
// create new menu for clicked on node
|
|
||||||
var rightclickmenu = document.createElement("div");
|
|
||||||
rightclickmenu.className = "rightclickmenu";
|
|
||||||
|
|
||||||
// add the proper options to the menu
|
|
||||||
var menustring = '<ul>';
|
|
||||||
|
|
||||||
if (userid != null) menustring += '<li class="rc-delete">Delete</li>';
|
|
||||||
if (mapid && userid != null) menustring += '<li class="rc-remove">Remove from map</li>';
|
|
||||||
menustring += '<li class="rc-hide">Hide until refresh</li>';
|
|
||||||
|
|
||||||
if (!mapid) menustring += '<li class="rc-center">Center this topic</li>';
|
|
||||||
menustring += '<li class="rc-popout">Open in new tab</li>';
|
|
||||||
if (userid) {
|
|
||||||
var options = '<ul><li class="changeP toCommons">commons</li> \
|
|
||||||
<li class="changeP toPublic">public</li> \
|
|
||||||
<li class="changeP toPrivate">private</li> \
|
|
||||||
</ul>';
|
|
||||||
|
|
||||||
menustring += '<li class="rc-permission">Change permissions' + options + '</li>';
|
|
||||||
}
|
|
||||||
|
|
||||||
menustring += '</ul>';
|
|
||||||
rightclickmenu.innerHTML = menustring;
|
|
||||||
|
|
||||||
// position the menu where the click happened
|
|
||||||
$(rightclickmenu).css({
|
|
||||||
left: e.clientX,
|
|
||||||
top: e.clientY
|
|
||||||
});
|
|
||||||
//add the menu to the page
|
|
||||||
$('#center-container').append(rightclickmenu);
|
|
||||||
|
|
||||||
|
|
||||||
// attach events to clicks on the list items
|
|
||||||
|
|
||||||
// delete the selected things from the database
|
|
||||||
$('.rc-delete').click(function () {
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
var n = MetamapsModel.selectedNodes.length;
|
|
||||||
var e = MetamapsModel.selectedEdges.length;
|
|
||||||
var ntext = n == 1 ? "1 topic" : n + " topics";
|
|
||||||
var etext = e == 1 ? "1 synapse" : e + " synapses";
|
|
||||||
var text = "You have " + ntext + " and " + etext + " selected. ";
|
|
||||||
|
|
||||||
var r = confirm(text + "Are you sure you want to permanently delete them all? This will remove them from all maps they appear on.");
|
|
||||||
if (r == true) {
|
|
||||||
deleteSelectedEdges();
|
|
||||||
deleteSelectedNodes();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// remove the selected things from the map
|
|
||||||
$('.rc-remove').click(function () {
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
removeSelectedEdges();
|
|
||||||
removeSelectedNodes();
|
|
||||||
});
|
|
||||||
|
|
||||||
// hide selected nodes and synapses until refresh
|
|
||||||
$('.rc-hide').click(function () {
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
hideSelectedEdges();
|
|
||||||
hideSelectedNodes();
|
|
||||||
});
|
|
||||||
|
|
||||||
// when in radial, center on the topic you picked
|
|
||||||
$('.rc-center').click(function () {
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
centerOn(node.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
// open the entity in a new tab
|
|
||||||
$('.rc-popout').click(function () {
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
var win = window.open('/topics/' + node.id, '_blank');
|
|
||||||
win.focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
// change the permission of all the selected nodes and synapses that you were the originator of
|
|
||||||
$('.rc-permission li').click(function () {
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
// $(this).text() will be 'commons' 'public' or 'private'
|
|
||||||
updateSelectedPermissions($(this).text());
|
|
||||||
});
|
|
||||||
|
|
||||||
} //selectNodeOnRightClickHandler
|
|
||||||
|
|
||||||
function canvasDoubleClickHandler(canvasLoc, e) {
|
|
||||||
|
|
||||||
//grab the location and timestamp of the click
|
|
||||||
var storedTime = MetamapsModel.lastCanvasClick;
|
|
||||||
var now = Date.now(); //not compatible with IE8 FYI
|
|
||||||
MetamapsModel.lastCanvasClick = now;
|
|
||||||
|
|
||||||
// if on a public map, disable topic creation
|
|
||||||
if (userid && (mapperm || !mapid)) {
|
|
||||||
if (now - storedTime < MetamapsModel.DOUBLE_CLICK_TOLERANCE) {
|
|
||||||
//pop up node creation :)
|
|
||||||
$('#topic_grabTopic').val("null");
|
|
||||||
$('#topic_addSynapse').val("false");
|
|
||||||
$('#new_topic').css('left', e.clientX + "px");
|
|
||||||
$('#new_topic').css('top', e.clientY + "px");
|
|
||||||
$('#topic_x').val(canvasLoc.x);
|
|
||||||
$('#topic_y').val(canvasLoc.y);
|
|
||||||
$('#new_topic').fadeIn('fast');
|
|
||||||
$('#topic_name').typeahead('setQuery', '').focus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!MetamapsModel.didPan) {
|
|
||||||
$('#new_topic').fadeOut('fast');
|
|
||||||
$('#new_synapse').fadeOut('fast');
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
// reset the draw synapse positions to false
|
|
||||||
MetamapsModel.synapseStartCoord = false;
|
|
||||||
MetamapsModel.synapseEndCoord = false;
|
|
||||||
deselectAllNodes();
|
|
||||||
tempInit = false;
|
|
||||||
tempNode = null;
|
|
||||||
tempNode2 = null;
|
|
||||||
Mconsole.plot();
|
|
||||||
}
|
|
||||||
} //canvasDoubleClickHandler
|
|
||||||
|
|
||||||
function handleSelectionBeforeDragging(node, e) {
|
|
||||||
// four cases:
|
|
||||||
// 1 nothing is selected, so pretend you aren't selecting
|
|
||||||
// 2 others are selected only and shift, so additionally select this one
|
|
||||||
// 3 others are selected only, no shift: drag only this one
|
|
||||||
// 4 this node and others were selected, so drag them (just return false)
|
|
||||||
//return value: deselect node again after?
|
|
||||||
if (MetamapsModel.selectedNodes.length == 0) {
|
|
||||||
selectNode(node);
|
|
||||||
return 'deselect';
|
|
||||||
}
|
|
||||||
if (MetamapsModel.selectedNodes.indexOf(node) == -1) {
|
|
||||||
if (e.shiftKey) {
|
|
||||||
selectNode(node);
|
|
||||||
return 'nothing';
|
|
||||||
} else {
|
|
||||||
return 'only-drag-this-one';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'nothing'; //case 4?
|
|
||||||
}
|
|
||||||
|
|
||||||
function onDragMoveTopicHandler(node, eventInfo, e) {
|
|
||||||
if (node && !node.nodeFrom) {
|
|
||||||
$('#new_synapse').fadeOut('fast');
|
|
||||||
$('#new_topic').fadeOut('fast');
|
|
||||||
var pos = eventInfo.getPos();
|
|
||||||
var newPosComplex = new $jit.Complex(pos.x, pos.y);
|
|
||||||
// if it's a left click, or a touch, move the node
|
|
||||||
if (e.touches || (e.button == 0 && !e.altKey && (e.buttons == 0 || e.buttons == 1 || e.buttons == undefined))) {
|
|
||||||
//if the node dragged isn't already selected, select it
|
|
||||||
var whatToDo = handleSelectionBeforeDragging(node, e);
|
|
||||||
if (whatToDo == 'only-drag-this-one' || whatToDo == 'deselect') {
|
|
||||||
if (gType == "centered") {
|
|
||||||
var rho = Math.sqrt(pos.x * pos.x + pos.y * pos.y);
|
|
||||||
var theta = Math.atan2(pos.y, pos.x);
|
|
||||||
node.pos.setp(theta, rho);
|
|
||||||
} else {
|
|
||||||
node.setPos(newPosComplex, 'start');
|
|
||||||
node.setPos(newPosComplex, 'current');
|
|
||||||
node.setPos(newPosComplex, 'end');
|
|
||||||
node.setData('xloc', pos.x);
|
|
||||||
node.setData('yloc', pos.y);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var len = MetamapsModel.selectedNodes.length;
|
|
||||||
|
|
||||||
//first define offset for each node
|
|
||||||
var xOffset = new Array();
|
|
||||||
var yOffset = new Array();
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
var n = MetamapsModel.selectedNodes[i];
|
|
||||||
if (gType == "centered") {
|
|
||||||
xOffset[i] = n.pos.toComplex().x - node.pos.toComplex().x;
|
|
||||||
yOffset[i] = n.pos.toComplex().y - node.pos.toComplex().y;
|
|
||||||
} else {
|
|
||||||
xOffset[i] = n.pos.x - node.pos.x;
|
|
||||||
yOffset[i] = n.pos.y - node.pos.y;
|
|
||||||
}
|
|
||||||
} //for
|
|
||||||
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
var n = MetamapsModel.selectedNodes[i];
|
|
||||||
if (gType == "centered") {
|
|
||||||
var x = pos.x + xOffset[i];
|
|
||||||
var y = pos.y + yOffset[i];
|
|
||||||
var rho = Math.sqrt(x * x + y * y);
|
|
||||||
var theta = Math.atan2(y, x);
|
|
||||||
n.pos.setp(theta, rho);
|
|
||||||
} else {
|
|
||||||
newPosComplex = new $jit.Complex(pos.x + xOffset[i], pos.y + yOffset[i]);
|
|
||||||
n.setPos(newPosComplex, 'start');
|
|
||||||
n.setPos(newPosComplex, 'current');
|
|
||||||
n.setPos(newPosComplex, 'end');
|
|
||||||
n.setData('xloc', pos.x + xOffset[i]);
|
|
||||||
n.setData('yloc', pos.y + yOffset[i]);
|
|
||||||
}
|
|
||||||
} //for
|
|
||||||
} //if
|
|
||||||
|
|
||||||
if (whatToDo == 'deselect') {
|
|
||||||
deselectNode(node);
|
|
||||||
}
|
|
||||||
dragged = node.id;
|
|
||||||
Mconsole.plot();
|
|
||||||
}
|
|
||||||
// if it's a right click or holding down alt, start synapse creation ->third option is for firefox
|
|
||||||
else if ((e.button == 2 || (e.button == 0 && e.altKey) || e.buttons == 2) && userid != null) {
|
|
||||||
|
|
||||||
// if on a public map, disable synapse creation
|
|
||||||
if (mapid && !mapperm) return;
|
|
||||||
|
|
||||||
if (tempInit == false) {
|
|
||||||
tempNode = node;
|
|
||||||
tempInit = true;
|
|
||||||
// set the draw synapse start position
|
|
||||||
MetamapsModel.synapseStartCoord = {
|
|
||||||
x: node.pos.getc().x,
|
|
||||||
y: node.pos.getc().y
|
|
||||||
};
|
|
||||||
}
|
|
||||||
//
|
|
||||||
temp = eventInfo.getNode();
|
|
||||||
if (temp != false && temp.id != node.id) { // this means a Node has been returned
|
|
||||||
tempNode2 = temp;
|
|
||||||
|
|
||||||
// set the draw synapse end position
|
|
||||||
MetamapsModel.synapseEndCoord = {
|
|
||||||
x: temp.pos.getc().x,
|
|
||||||
y: temp.pos.getc().y
|
|
||||||
};
|
|
||||||
|
|
||||||
Mconsole.plot();
|
|
||||||
|
|
||||||
// before making the highlighted one bigger, make sure all the others are regular size
|
|
||||||
Mconsole.graph.eachNode(function (n) {
|
|
||||||
n.setData('dim', 25, 'current');
|
|
||||||
});
|
|
||||||
temp.setData('dim', 35, 'current');
|
|
||||||
Mconsole.fx.plotNode(tempNode, Mconsole.canvas);
|
|
||||||
Mconsole.fx.plotNode(temp, Mconsole.canvas);
|
|
||||||
} else if (!temp) {
|
|
||||||
tempNode2 = null;
|
|
||||||
Mconsole.graph.eachNode(function (n) {
|
|
||||||
n.setData('dim', 25, 'current');
|
|
||||||
});
|
|
||||||
//pop up node creation :)
|
|
||||||
$('#topic_grabTopic').val("null");
|
|
||||||
var myX = e.clientX - 110;
|
|
||||||
var myY = e.clientY - 30;
|
|
||||||
$('#new_topic').css('left', myX + "px");
|
|
||||||
$('#new_topic').css('top', myY + "px");
|
|
||||||
$('#new_synapse').css('left', myX + "px");
|
|
||||||
$('#new_synapse').css('top', myY + "px");
|
|
||||||
$('#topic_x').val(eventInfo.getPos().x);
|
|
||||||
$('#topic_y').val(eventInfo.getPos().y);
|
|
||||||
// set the draw synapse end position
|
|
||||||
MetamapsModel.synapseEndCoord = {
|
|
||||||
x: eventInfo.getPos().x,
|
|
||||||
y: eventInfo.getPos().y
|
|
||||||
};
|
|
||||||
Mconsole.plot();
|
|
||||||
Mconsole.fx.plotNode(tempNode, Mconsole.canvas);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastDist = 0;
|
|
||||||
|
|
||||||
function getDistance(p1, p2) {
|
|
||||||
return Math.sqrt(Math.pow((p2.x - p1.x), 2) + Math.pow((p2.y - p1.y), 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
function touchPanZoomHandler(eventInfo, e) {
|
|
||||||
if (e.touches.length == 1) {
|
|
||||||
var thispos = touchPos,
|
|
||||||
currentPos = eventInfo.getPos(),
|
|
||||||
canvas = Mconsole.canvas,
|
|
||||||
ox = canvas.translateOffsetX,
|
|
||||||
oy = canvas.translateOffsetY,
|
|
||||||
sx = canvas.scaleOffsetX,
|
|
||||||
sy = canvas.scaleOffsetY;
|
|
||||||
currentPos.x *= sx;
|
|
||||||
currentPos.y *= sy;
|
|
||||||
currentPos.x += ox;
|
|
||||||
currentPos.y += oy;
|
|
||||||
//var x = currentPos.x - thispos.x,
|
|
||||||
// y = currentPos.y - thispos.y;
|
|
||||||
var x = currentPos.x - thispos.x,
|
|
||||||
y = currentPos.y - thispos.y;
|
|
||||||
touchPos = currentPos;
|
|
||||||
Mconsole.canvas.translate(x * 1 / sx, y * 1 / sy);
|
|
||||||
} else if (e.touches.length == 2) {
|
|
||||||
var touch1 = e.touches[0];
|
|
||||||
var touch2 = e.touches[1];
|
|
||||||
|
|
||||||
var dist = getDistance({
|
|
||||||
x: touch1.clientX,
|
|
||||||
y: touch1.clientY
|
|
||||||
}, {
|
|
||||||
x: touch2.clientX,
|
|
||||||
y: touch2.clientY
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!lastDist) {
|
|
||||||
lastDist = dist;
|
|
||||||
}
|
|
||||||
|
|
||||||
var scale = dist / lastDist;
|
|
||||||
|
|
||||||
console.log(scale);
|
|
||||||
|
|
||||||
if (8 >= Mconsole.canvas.scaleOffsetX * scale && Mconsole.canvas.scaleOffsetX * scale >= 1) {
|
|
||||||
Mconsole.canvas.scale(scale, scale);
|
|
||||||
}
|
|
||||||
if (Mconsole.canvas.scaleOffsetX < 0.5) {
|
|
||||||
Mconsole.canvas.viz.labels.hideLabels(true);
|
|
||||||
} else if (Mconsole.canvas.scaleOffsetX > 0.5) {
|
|
||||||
Mconsole.canvas.viz.labels.hideLabels(false);
|
|
||||||
}
|
|
||||||
lastDist = dist;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateSelectedPermissions(permission) {
|
|
||||||
|
|
||||||
|
|
||||||
if ($('.notice.metamaps').length == 0) {
|
|
||||||
$('body').prepend('<div class="notice metamaps" />');
|
|
||||||
}
|
|
||||||
$('.notice.metamaps').hide().html('Working...').fadeIn('fast');
|
|
||||||
|
|
||||||
// variables to keep track of how many nodes and synapses you had the ability to change the permission of
|
|
||||||
var nCount = 0,
|
|
||||||
sCount = 0;
|
|
||||||
|
|
||||||
// change the permission of the selected synapses, if logged in user is the original creator
|
|
||||||
var l = MetamapsModel.selectedEdges.length;
|
|
||||||
for (var i = l - 1; i >= 0; i -= 1) {
|
|
||||||
var edge = MetamapsModel.selectedEdges[i];
|
|
||||||
|
|
||||||
if (edge.getData('userid') == userid) {
|
|
||||||
updateSynapsePermission(edge, permission);
|
|
||||||
sCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// change the permission of the selected topics, if logged in user is the original creator
|
|
||||||
var l = MetamapsModel.selectedNodes.length;
|
|
||||||
for (var i = l - 1; i >= 0; i -= 1) {
|
|
||||||
var node = MetamapsModel.selectedNodes[i];
|
|
||||||
|
|
||||||
if (node.getData('userid') == userid) {
|
|
||||||
updateTopicPermission(node, permission);
|
|
||||||
nCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var nString = nCount == 1 ? (nCount.toString() + ' topic and ') : (nCount.toString() + ' topics and ');
|
|
||||||
var sString = sCount == 1 ? (sCount.toString() + ' synapse') : (sCount.toString() + ' synapses');
|
|
||||||
|
|
||||||
$('.notice.metamaps').html(nString + sString + ' you created updated to ' + permission)
|
|
||||||
setTimeout(function () {
|
|
||||||
$('.notice.metamaps').fadeOut('fast');
|
|
||||||
}, 8000);
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
* @file
|
|
||||||
* This file holds the Model object that is referenced in other graphsettings
|
|
||||||
* files. It lists selected nodes, selected edges, and stores data about
|
|
||||||
* double clicks on the canvas
|
|
||||||
*/
|
|
||||||
|
|
||||||
var MetamapsModel = new Object();
|
|
||||||
|
|
||||||
MetamapsModel.embed = false;
|
|
||||||
|
|
||||||
// if you're on a map, this will be an object that has a reference to each user that has loaded the map, and whether they are
|
|
||||||
// in realtime or not
|
|
||||||
MetamapsModel.mappersOnMap = {};
|
|
||||||
|
|
||||||
|
|
||||||
MetamapsModel.metacodeScrollerInit = false; // indicates whether the scrollbar in the custom metacode set space has been init
|
|
||||||
|
|
||||||
MetamapsModel.selectedMetacodeSet = null;
|
|
||||||
MetamapsModel.selectedMetacodeSetIndex = null;
|
|
||||||
|
|
||||||
MetamapsModel.selectedMetacodeNames = new Array();
|
|
||||||
MetamapsModel.newSelectedMetacodeNames = new Array();
|
|
||||||
|
|
||||||
MetamapsModel.selectedMetacodes = new Array();
|
|
||||||
MetamapsModel.newSelectedMetacodes = new Array();
|
|
||||||
|
|
||||||
//array of all selected edges, same for nodes
|
|
||||||
MetamapsModel.selectedEdges = new Array();
|
|
||||||
MetamapsModel.selectedNodes = new Array();
|
|
||||||
|
|
||||||
//this stores a value that indicates whether the user panned or simply clicked without panning
|
|
||||||
// used for purposes of knowing whether to close the open card or not (don't if panned)
|
|
||||||
MetamapsModel.didPan = false;
|
|
||||||
|
|
||||||
//is any showcard open right now? which one?
|
|
||||||
MetamapsModel.showcardInUse = null;
|
|
||||||
MetamapsModel.widthOfLabel = null;
|
|
||||||
|
|
||||||
//is an edge card open right now? which one (the id)?
|
|
||||||
MetamapsModel.edgecardInUse = null;
|
|
||||||
|
|
||||||
//is the mouse hovering over an edge? which one?
|
|
||||||
MetamapsModel.edgeHoveringOver = false;
|
|
||||||
|
|
||||||
//coordinates of shift click for using box select
|
|
||||||
MetamapsModel.boxStartCoordinates = false;
|
|
||||||
MetamapsModel.boxEndCoordinates = false;
|
|
||||||
|
|
||||||
//coordinates for drawing edge that's not created yet
|
|
||||||
MetamapsModel.synapseStartCoord = false;
|
|
||||||
MetamapsModel.synapseEndCoord = false;
|
|
||||||
|
|
||||||
//double clicking of nodes or canvas
|
|
||||||
MetamapsModel.lastSynapseClick = 0;
|
|
||||||
MetamapsModel.lastNodeClick = 0;
|
|
||||||
MetamapsModel.lastCanvasClick = 0;
|
|
||||||
MetamapsModel.DOUBLE_CLICK_TOLERANCE = 300;
|
|
||||||
|
|
||||||
//pop-up permission editors timers
|
|
||||||
MetamapsModel.edgePermTimer1 = null;
|
|
||||||
MetamapsModel.edgePermTimer2 = null;
|
|
||||||
MetamapsModel.edgePermSliding = false;
|
|
||||||
MetamapsModel.topicPermTimer1 = null;
|
|
||||||
MetamapsModel.topicPermTimer2 = null;
|
|
||||||
MetamapsModel.topicPermSliding = false;
|
|
|
@ -1,606 +0,0 @@
|
||||||
/*
|
|
||||||
* @file
|
|
||||||
* This function defines all settings and event callbacks for the JIT graph. Some are found in other files
|
|
||||||
* First is the common settings (the same as arranged or chaotic)
|
|
||||||
* Then if it's a centred graph additional settings are added.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function graphSettings(type, embed) {
|
|
||||||
var t = {
|
|
||||||
//id of the visualization container
|
|
||||||
injectInto: 'infovis',
|
|
||||||
//Enable zooming and panning
|
|
||||||
//by scrolling and DnD
|
|
||||||
Navigation: {
|
|
||||||
enable: true,
|
|
||||||
//Enable panning events only if we're dragging the empty
|
|
||||||
//canvas (and not a node).
|
|
||||||
panning: 'avoid nodes',
|
|
||||||
zooming: 28 //zoom speed. higher is more sensible
|
|
||||||
},
|
|
||||||
// Change node and edge styles such as
|
|
||||||
// color and width.
|
|
||||||
// These properties are also set per node
|
|
||||||
// with dollar prefixed data-properties in the
|
|
||||||
// JSON structure.
|
|
||||||
Node: {
|
|
||||||
overridable: true,
|
|
||||||
color: '#2D6A5D',
|
|
||||||
type: 'customNode',
|
|
||||||
dim: 25
|
|
||||||
},
|
|
||||||
Edge: {
|
|
||||||
overridable: true,
|
|
||||||
color: '#222222',
|
|
||||||
type: 'customEdge',
|
|
||||||
lineWidth: 2,
|
|
||||||
alpha: 0.4
|
|
||||||
},
|
|
||||||
//Native canvas text styling
|
|
||||||
Label: {
|
|
||||||
type: 'Native', //Native or HTML
|
|
||||||
size: 20,
|
|
||||||
family: 'arial',
|
|
||||||
textBaseline: 'hanging',
|
|
||||||
color: '#DDD'
|
|
||||||
//style: 'bold'
|
|
||||||
},
|
|
||||||
//Add Tips
|
|
||||||
Tips: {
|
|
||||||
enable: false,
|
|
||||||
onShow: function (tip, node) {}
|
|
||||||
},
|
|
||||||
// Add node events
|
|
||||||
Events: {
|
|
||||||
enable: true,
|
|
||||||
enableForEdges: true,
|
|
||||||
onMouseMove: function (node, eventInfo, e) {
|
|
||||||
onMouseMoveHandler(node, eventInfo, e);
|
|
||||||
},
|
|
||||||
//Update node positions when dragged
|
|
||||||
onDragMove: function (node, eventInfo, e) {
|
|
||||||
onDragMoveTopicHandler(node, eventInfo, e);
|
|
||||||
},
|
|
||||||
onDragEnd: function (node, eventInfo, e) {
|
|
||||||
onDragEndTopicHandler(node, eventInfo, e, false);
|
|
||||||
},
|
|
||||||
onDragCancel: function (node, eventInfo, e) {
|
|
||||||
onDragCancelHandler(node, eventInfo, e, false);
|
|
||||||
},
|
|
||||||
//Implement the same handler for touchscreens
|
|
||||||
onTouchStart: function (node, eventInfo, e) {
|
|
||||||
//$jit.util.event.stop(e); //stop default touchmove event
|
|
||||||
//Mconsole.events.onMouseDown(e, null, eventInfo);
|
|
||||||
Mconsole.events.touched = true;
|
|
||||||
touchPos = eventInfo.getPos();
|
|
||||||
var canvas = Mconsole.canvas,
|
|
||||||
ox = canvas.translateOffsetX;
|
|
||||||
oy = canvas.translateOffsetY,
|
|
||||||
sx = canvas.scaleOffsetX,
|
|
||||||
sy = canvas.scaleOffsetY;
|
|
||||||
touchPos.x *= sx;
|
|
||||||
touchPos.y *= sy;
|
|
||||||
touchPos.x += ox;
|
|
||||||
touchPos.y += oy;
|
|
||||||
|
|
||||||
touchDragNode = node;
|
|
||||||
},
|
|
||||||
//Implement the same handler for touchscreens
|
|
||||||
onTouchMove: function (node, eventInfo, e) {
|
|
||||||
if (touchDragNode) onDragMoveTopicHandler(touchDragNode, eventInfo, e);
|
|
||||||
else {
|
|
||||||
touchPanZoomHandler(eventInfo, e);
|
|
||||||
Mconsole.labels.hideLabel(Mconsole.graph.getNode(MetamapsModel.showcardInUse));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
//Implement the same handler for touchscreens
|
|
||||||
onTouchEnd: function (node, eventInfo, e) {
|
|
||||||
|
|
||||||
},
|
|
||||||
//Implement the same handler for touchscreens
|
|
||||||
onTouchCancel: function (node, eventInfo, e) {
|
|
||||||
|
|
||||||
},
|
|
||||||
//Add also a click handler to nodes
|
|
||||||
onClick: function (node, eventInfo, e) {
|
|
||||||
if (MetamapsModel.boxStartCoordinates) {
|
|
||||||
Mconsole.busy = false;
|
|
||||||
MetamapsModel.boxEndCoordinates = eventInfo.getPos();
|
|
||||||
selectNodesWithBox();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.target.id != "infovis-canvas") return false;
|
|
||||||
|
|
||||||
//clicking on a edge, node, or clicking on blank part of canvas?
|
|
||||||
if (node.nodeFrom) {
|
|
||||||
selectEdgeOnClickHandler(node, e);
|
|
||||||
} else if (node && !node.nodeFrom) {
|
|
||||||
selectNodeOnClickHandler(node, e);
|
|
||||||
} else {
|
|
||||||
//topic and synapse editing cards
|
|
||||||
if (!MetamapsModel.didPan) {
|
|
||||||
hideCards();
|
|
||||||
}
|
|
||||||
canvasDoubleClickHandler(eventInfo.getPos(), e);
|
|
||||||
} //if
|
|
||||||
},
|
|
||||||
onRightClick: function (node, eventInfo, e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
if (node && !node.nodeFrom) {
|
|
||||||
selectNodeOnRightClickHandler(node, e);
|
|
||||||
} else if (node && node.nodeFrom) { // the variable 'node' is actually an edge/adjacency
|
|
||||||
// open right click menu
|
|
||||||
selectEdgeOnRightClickHandler(node, e);
|
|
||||||
} else {
|
|
||||||
// right click on open canvas, options here?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
//Number of iterations for the FD algorithm
|
|
||||||
iterations: 200,
|
|
||||||
//Edge length
|
|
||||||
levelDistance: 200
|
|
||||||
};
|
|
||||||
|
|
||||||
if (embed) {
|
|
||||||
t.Edge.type = 'customEdgeEmbed';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == "centered") {
|
|
||||||
t.background = {
|
|
||||||
CanvasStyles: {
|
|
||||||
strokeStyle: '#333',
|
|
||||||
lineWidth: 1.5
|
|
||||||
}
|
|
||||||
};
|
|
||||||
t.levelDistance = 280;
|
|
||||||
t.Events.enableForEdges = true;
|
|
||||||
t.Events.onDragEnd = function (node, eventInfo, e) {
|
|
||||||
//different because we can't go realtime
|
|
||||||
onDragEndTopicHandler(node, eventInfo, e, false);
|
|
||||||
};
|
|
||||||
t.Events.onDragCancel = function (node, eventInfo, e) {
|
|
||||||
//different because we're centred
|
|
||||||
onDragCancelHandler(node, eventInfo, e, true);
|
|
||||||
};
|
|
||||||
} //if
|
|
||||||
|
|
||||||
return t;
|
|
||||||
} //graphSettings
|
|
||||||
|
|
||||||
function hideCards() {
|
|
||||||
$('#edit_synapse').hide();
|
|
||||||
MetamapsModel.edgecardInUse = null;
|
|
||||||
hideCurrentCard();
|
|
||||||
// delete right click menu
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// defining code to draw edges with arrows pointing in one direction
|
|
||||||
var renderMidArrow = function (from, to, dim, swap, canvas, placement, newSynapse) {
|
|
||||||
var ctx = canvas.getCtx();
|
|
||||||
// invert edge direction
|
|
||||||
if (swap) {
|
|
||||||
var tmp = from;
|
|
||||||
from = to;
|
|
||||||
to = tmp;
|
|
||||||
}
|
|
||||||
// vect represents a line from tip to tail of the arrow
|
|
||||||
var vect = new $jit.Complex(to.x - from.x, to.y - from.y);
|
|
||||||
// scale it
|
|
||||||
vect.$scale(dim / vect.norm());
|
|
||||||
// compute the midpoint of the edge line
|
|
||||||
var newX = (to.x - from.x) * placement + from.x;
|
|
||||||
var newY = (to.y - from.y) * placement + from.y;
|
|
||||||
var midPoint = new $jit.Complex(newX, newY);
|
|
||||||
|
|
||||||
// move midpoint by half the "length" of the arrow so the arrow is centered on the midpoint
|
|
||||||
var arrowPoint = new $jit.Complex((vect.x / 0.7) + midPoint.x, (vect.y / 0.7) + midPoint.y);
|
|
||||||
// compute the tail intersection point with the edge line
|
|
||||||
var intermediatePoint = new $jit.Complex(arrowPoint.x - vect.x, arrowPoint.y - vect.y);
|
|
||||||
// vector perpendicular to vect
|
|
||||||
var normal = new $jit.Complex(-vect.y / 2, vect.x / 2);
|
|
||||||
var v1 = intermediatePoint.add(normal);
|
|
||||||
var v2 = intermediatePoint.$add(normal.$scale(-1));
|
|
||||||
|
|
||||||
if (newSynapse) {
|
|
||||||
ctx.strokeStyle = "#222222";
|
|
||||||
ctx.lineWidth = 2;
|
|
||||||
ctx.globalAlpha = 0.4;
|
|
||||||
}
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.moveTo(from.x, from.y);
|
|
||||||
ctx.lineTo(to.x, to.y);
|
|
||||||
ctx.stroke();
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.moveTo(v1.x, v1.y);
|
|
||||||
ctx.lineTo(arrowPoint.x, arrowPoint.y);
|
|
||||||
ctx.lineTo(v2.x, v2.y);
|
|
||||||
ctx.stroke();
|
|
||||||
};
|
|
||||||
|
|
||||||
// defining custom node type
|
|
||||||
var nodeSettings = {
|
|
||||||
'customNode': {
|
|
||||||
'render': function (node, canvas) {
|
|
||||||
var pos = node.pos.getc(true),
|
|
||||||
dim = node.getData('dim'),
|
|
||||||
cat = node.getData('metacode'),
|
|
||||||
whiteCircle = node.getData('whiteCircle'),
|
|
||||||
ctx = canvas.getCtx();
|
|
||||||
|
|
||||||
// if the topic is on the Canvas draw a white circle around it
|
|
||||||
if (whiteCircle) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.arc(pos.x, pos.y, dim + 3, 0, 2 * Math.PI, false);
|
|
||||||
if (!MetamapsModel.embed) ctx.strokeStyle = 'white';
|
|
||||||
if (MetamapsModel.embed) ctx.strokeStyle = '#999';
|
|
||||||
ctx.lineWidth = 2;
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
ctx.drawImage(imgArray[cat], pos.x - dim, pos.y - dim, dim * 2, dim * 2);
|
|
||||||
|
|
||||||
},
|
|
||||||
'contains': function (node, pos) {
|
|
||||||
var npos = node.pos.getc(true),
|
|
||||||
dim = node.getData('dim');
|
|
||||||
return this.nodeHelper.circle.contains(npos, pos, dim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var renderEdgeArrows = function (edgeHelper, adj) {
|
|
||||||
var canvas = Mconsole.canvas;
|
|
||||||
var directionCat = adj.getData('category');
|
|
||||||
var direction = adj.getData('direction');
|
|
||||||
var pos = adj.nodeFrom.pos.getc(true);
|
|
||||||
var posChild = adj.nodeTo.pos.getc(true);
|
|
||||||
|
|
||||||
//plot arrow edge
|
|
||||||
if (directionCat == "none") {
|
|
||||||
edgeHelper.line.render({
|
|
||||||
x: pos.x,
|
|
||||||
y: pos.y
|
|
||||||
}, {
|
|
||||||
x: posChild.x,
|
|
||||||
y: posChild.y
|
|
||||||
}, canvas);
|
|
||||||
} else if (directionCat == "both") {
|
|
||||||
renderMidArrow({
|
|
||||||
x: pos.x,
|
|
||||||
y: pos.y
|
|
||||||
}, {
|
|
||||||
x: posChild.x,
|
|
||||||
y: posChild.y
|
|
||||||
}, 13, true, canvas, 0.7);
|
|
||||||
renderMidArrow({
|
|
||||||
x: pos.x,
|
|
||||||
y: pos.y
|
|
||||||
}, {
|
|
||||||
x: posChild.x,
|
|
||||||
y: posChild.y
|
|
||||||
}, 13, false, canvas, 0.7);
|
|
||||||
} else if (directionCat == "from-to") {
|
|
||||||
var direction = adj.data.$direction;
|
|
||||||
var inv = (direction && direction.length > 1 && direction[0] != adj.nodeFrom.id);
|
|
||||||
renderMidArrow({
|
|
||||||
x: pos.x,
|
|
||||||
y: pos.y
|
|
||||||
}, {
|
|
||||||
x: posChild.x,
|
|
||||||
y: posChild.y
|
|
||||||
}, 13, inv, canvas, 0.7);
|
|
||||||
renderMidArrow({
|
|
||||||
x: pos.x,
|
|
||||||
y: pos.y
|
|
||||||
}, {
|
|
||||||
x: posChild.x,
|
|
||||||
y: posChild.y
|
|
||||||
}, 13, inv, canvas, 0.3);
|
|
||||||
}
|
|
||||||
} //renderEdgeArrow
|
|
||||||
|
|
||||||
// defining custom edges
|
|
||||||
var edgeSettings = {
|
|
||||||
'customEdge': {
|
|
||||||
'render': function (adj, canvas) {
|
|
||||||
//get nodes cartesian coordinates
|
|
||||||
var pos = adj.nodeFrom.pos.getc(true);
|
|
||||||
var posChild = adj.nodeTo.pos.getc(true);
|
|
||||||
|
|
||||||
var directionCat = adj.getData("category");
|
|
||||||
//label placement on edges
|
|
||||||
renderEdgeArrows(this.edgeHelper, adj);
|
|
||||||
|
|
||||||
//check for edge label in data
|
|
||||||
var desc = adj.getData("desc");
|
|
||||||
var showDesc = adj.getData("showDesc");
|
|
||||||
if (desc != "" && showDesc) {
|
|
||||||
// '&' to '&'
|
|
||||||
desc = decodeEntities(desc);
|
|
||||||
|
|
||||||
//now adjust the label placement
|
|
||||||
var ctx = canvas.getCtx();
|
|
||||||
ctx.font = 'bold 14px arial';
|
|
||||||
ctx.fillStyle = '#FFF';
|
|
||||||
ctx.textBaseline = 'hanging';
|
|
||||||
|
|
||||||
// helper function to determine how many lines are needed
|
|
||||||
// Line Splitter Function
|
|
||||||
// copyright Stephen Chapman, 19th April 2006
|
|
||||||
// you may copy this code but please keep the copyright notice as well
|
|
||||||
function splitLine(st, n) {
|
|
||||||
var b = '';
|
|
||||||
var s = st;
|
|
||||||
while (s.length > n) {
|
|
||||||
var c = s.substring(0, n);
|
|
||||||
var d = c.lastIndexOf(' ');
|
|
||||||
var e = c.lastIndexOf('\n');
|
|
||||||
if (e != -1) d = e;
|
|
||||||
if (d == -1) d = n;
|
|
||||||
b += c.substring(0, d) + '\n';
|
|
||||||
s = s.substring(d + 1);
|
|
||||||
}
|
|
||||||
return b + s;
|
|
||||||
}
|
|
||||||
var arrayOfLabelLines = splitLine(desc, 30).split('\n');
|
|
||||||
var index, lineWidths = [];
|
|
||||||
for (index = 0; index < arrayOfLabelLines.length; ++index) {
|
|
||||||
lineWidths.push(ctx.measureText(arrayOfLabelLines[index]).width)
|
|
||||||
}
|
|
||||||
var width = Math.max.apply(null, lineWidths) + 8;
|
|
||||||
var height = (16 * arrayOfLabelLines.length) + 8;
|
|
||||||
|
|
||||||
var x = (pos.x + posChild.x - width) / 2;
|
|
||||||
var y = ((pos.y + posChild.y) / 2) - height / 2;
|
|
||||||
var radius = 5;
|
|
||||||
|
|
||||||
//render background
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.moveTo(x + radius, y);
|
|
||||||
ctx.lineTo(x + width - radius, y);
|
|
||||||
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
|
|
||||||
ctx.lineTo(x + width, y + height - radius);
|
|
||||||
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
|
|
||||||
ctx.lineTo(x + radius, y + height);
|
|
||||||
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
|
|
||||||
ctx.lineTo(x, y + radius);
|
|
||||||
ctx.quadraticCurveTo(x, y, x + radius, y);
|
|
||||||
ctx.closePath();
|
|
||||||
ctx.fill();
|
|
||||||
|
|
||||||
//render text
|
|
||||||
ctx.fillStyle = '#222222';
|
|
||||||
ctx.textAlign = 'center';
|
|
||||||
for (index = 0; index < arrayOfLabelLines.length; ++index) {
|
|
||||||
ctx.fillText(arrayOfLabelLines[index], x + (width / 2), y + 5 + (16 * index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'contains': function (adj, pos) {
|
|
||||||
var from = adj.nodeFrom.pos.getc(true),
|
|
||||||
to = adj.nodeTo.pos.getc(true);
|
|
||||||
return this.edgeHelper.line.contains(from, to, pos, adj.Edge.epsilon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var edgeSettingsEmbed = {
|
|
||||||
'customEdgeEmbed': {
|
|
||||||
'render': function (adj, canvas) {
|
|
||||||
//get nodes cartesian coordinates
|
|
||||||
var pos = adj.nodeFrom.pos.getc(true);
|
|
||||||
var posChild = adj.nodeTo.pos.getc(true);
|
|
||||||
|
|
||||||
var directionCat = adj.getData("category");
|
|
||||||
//label placement on edges
|
|
||||||
renderEdgeArrows(this.edgeHelper, adj);
|
|
||||||
|
|
||||||
//check for edge label in data
|
|
||||||
var desc = adj.getData("desc");
|
|
||||||
var showDesc = adj.getData("showDesc");
|
|
||||||
if (desc != "" && showDesc) {
|
|
||||||
// '&' to '&'
|
|
||||||
desc = decodeEntities(desc);
|
|
||||||
|
|
||||||
//now adjust the label placement
|
|
||||||
var ctx = canvas.getCtx();
|
|
||||||
var radius = canvas.getSize();
|
|
||||||
var x = parseInt((pos.x + posChild.x - (desc.length * 5)) / 2);
|
|
||||||
var y = parseInt((pos.y + posChild.y) / 2);
|
|
||||||
ctx.font = 'bold 14px arial';
|
|
||||||
|
|
||||||
//render background
|
|
||||||
ctx.fillStyle = '#999';
|
|
||||||
var margin = 5;
|
|
||||||
var height = 14 + margin; //font size + margin
|
|
||||||
var CURVE = height / 2; //offset for curvy corners
|
|
||||||
var width = ctx.measureText(desc).width + 2 * margin - 2 * CURVE
|
|
||||||
var labelX = x - margin + CURVE;
|
|
||||||
var labelY = y - height + margin;
|
|
||||||
ctx.fillRect(labelX, labelY, width, height);
|
|
||||||
|
|
||||||
//curvy corners woo - circles in place of last CURVE pixels of rect
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.arc(labelX, labelY + CURVE, CURVE, 0, 2 * Math.PI, false);
|
|
||||||
ctx.arc(labelX + width, labelY + CURVE, CURVE, 0, 2 * Math.PI, false);
|
|
||||||
ctx.fill();
|
|
||||||
|
|
||||||
//render text
|
|
||||||
ctx.fillStyle = '#000';
|
|
||||||
ctx.fillText(desc, x, y);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'contains': function (adj, pos) {
|
|
||||||
var from = adj.nodeFrom.pos.getc(true),
|
|
||||||
to = adj.nodeTo.pos.getc(true);
|
|
||||||
return this.edgeHelper.line.contains(from, to, pos, adj.Edge.epsilon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawSelectBox(eventInfo, e) {
|
|
||||||
Mconsole.plot();
|
|
||||||
var ctx = Mconsole.canvas.getCtx();
|
|
||||||
|
|
||||||
var startX = MetamapsModel.boxStartCoordinates.x,
|
|
||||||
startY = MetamapsModel.boxStartCoordinates.y,
|
|
||||||
currX = eventInfo.getPos().x,
|
|
||||||
currY = eventInfo.getPos().y;
|
|
||||||
|
|
||||||
Mconsole.plot();
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.moveTo(startX, startY);
|
|
||||||
ctx.lineTo(startX, currY);
|
|
||||||
ctx.lineTo(currX, currY);
|
|
||||||
ctx.lineTo(currX, startY);
|
|
||||||
ctx.lineTo(startX, startY);
|
|
||||||
ctx.strokeStyle = "black";
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectNodesWithBox() {
|
|
||||||
|
|
||||||
var sX = MetamapsModel.boxStartCoordinates.x,
|
|
||||||
sY = MetamapsModel.boxStartCoordinates.y,
|
|
||||||
eX = MetamapsModel.boxEndCoordinates.x,
|
|
||||||
eY = MetamapsModel.boxEndCoordinates.y;
|
|
||||||
|
|
||||||
|
|
||||||
Mconsole.graph.eachNode(function (n) {
|
|
||||||
var x = gType == "centered" ? n.pos.toComplex().x : n.pos.x,
|
|
||||||
y = gType == "centered" ? n.pos.toComplex().y : n.pos.y;
|
|
||||||
|
|
||||||
if ((sX < x && x < eX && sY < y && y < eY) || (sX > x && x > eX && sY > y && y > eY) || (sX > x && x > eX && sY < y && y < eY) || (sX < x && x < eX && sY > y && y > eY)) {
|
|
||||||
var nodeIsSelected = MetamapsModel.selectedNodes.indexOf(n);
|
|
||||||
if (nodeIsSelected == -1) selectNode(n); // the node is not selected, so select it
|
|
||||||
else if (nodeIsSelected != -1) deselectNode(n); // the node is selected, so deselect it
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
MetamapsModel.boxStartCoordinates = false;
|
|
||||||
MetamapsModel.boxEndCoordinates = false;
|
|
||||||
Mconsole.plot();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMouseMoveHandler(node, eventInfo, e) {
|
|
||||||
|
|
||||||
if (Mconsole.busy) return;
|
|
||||||
|
|
||||||
var node = eventInfo.getNode();
|
|
||||||
var edge = eventInfo.getEdge();
|
|
||||||
|
|
||||||
//if we're on top of a node object, act like there aren't edges under it
|
|
||||||
if (node != false) {
|
|
||||||
if (MetamapsModel.edgeHoveringOver) {
|
|
||||||
onMouseLeave(MetamapsModel.edgeHoveringOver);
|
|
||||||
}
|
|
||||||
$('canvas').css('cursor', 'pointer');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (edge == false && MetamapsModel.edgeHoveringOver != false) {
|
|
||||||
//mouse not on an edge, but we were on an edge previously
|
|
||||||
onMouseLeave(MetamapsModel.edgeHoveringOver);
|
|
||||||
} else if (edge != false && MetamapsModel.edgeHoveringOver == false) {
|
|
||||||
//mouse is on an edge, but there isn't a stored edge
|
|
||||||
onMouseEnter(edge);
|
|
||||||
} else if (edge != false && MetamapsModel.edgeHoveringOver != edge) {
|
|
||||||
//mouse is on an edge, but a different edge is stored
|
|
||||||
onMouseLeave(MetamapsModel.edgeHoveringOver)
|
|
||||||
onMouseEnter(edge);
|
|
||||||
}
|
|
||||||
|
|
||||||
//could be false
|
|
||||||
MetamapsModel.edgeHoveringOver = edge;
|
|
||||||
|
|
||||||
if (!node && !edge) {
|
|
||||||
$('canvas').css('cursor', 'default');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMouseEnter(edge) {
|
|
||||||
$('canvas').css('cursor', 'pointer');
|
|
||||||
var edgeIsSelected = MetamapsModel.selectedEdges.indexOf(edge);
|
|
||||||
//following if statement only executes if the edge being hovered over is not selected
|
|
||||||
if (edgeIsSelected == -1) {
|
|
||||||
edge.setData('showDesc', true, 'current');
|
|
||||||
edge.setDataset('end', {
|
|
||||||
lineWidth: 4,
|
|
||||||
alpha: 1
|
|
||||||
});
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['edge-property:lineWidth:color:alpha'],
|
|
||||||
duration: 100
|
|
||||||
});
|
|
||||||
Mconsole.plot();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMouseLeave(edge) {
|
|
||||||
$('canvas').css('cursor', 'default');
|
|
||||||
var edgeIsSelected = MetamapsModel.selectedEdges.indexOf(edge);
|
|
||||||
//following if statement only executes if the edge being hovered over is not selected
|
|
||||||
if (edgeIsSelected == -1) {
|
|
||||||
edge.setData('showDesc', false, 'current');
|
|
||||||
edge.setDataset('end', {
|
|
||||||
lineWidth: 2,
|
|
||||||
alpha: 0.4
|
|
||||||
});
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['edge-property:lineWidth:color:alpha'],
|
|
||||||
duration: 100
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Mconsole.plot();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onDragEndTopicHandler(node, eventInfo, e, allowRealtime) {
|
|
||||||
if (tempInit && tempNode2 == null) {
|
|
||||||
$('#topic_addSynapse').val("true");
|
|
||||||
$('#new_topic').fadeIn('fast');
|
|
||||||
$('#topic_name').focus();
|
|
||||||
} else if (tempInit && tempNode2 != null) {
|
|
||||||
$('#topic_addSynapse').val("false");
|
|
||||||
$('#synapse_topic1id').val(tempNode.id);
|
|
||||||
$('#synapse_topic2id').val(tempNode2.id);
|
|
||||||
$('#new_synapse').fadeIn('fast');
|
|
||||||
$('#synapse_desc').typeahead('setQuery', '').focus();
|
|
||||||
tempNode = null;
|
|
||||||
tempNode2 = null;
|
|
||||||
tempInit = false;
|
|
||||||
} else if (dragged && dragged != 0 && goRealtime) {
|
|
||||||
saveLayout(dragged);
|
|
||||||
for (var i = 0; i < MetamapsModel.selectedNodes.length; i++) {
|
|
||||||
saveLayout(MetamapsModel.selectedNodes[i].id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} //onDragEndTopicHandler
|
|
||||||
|
|
||||||
function onDragCancelHandler(node, eventInfo, e, centred) {
|
|
||||||
tempNode = null;
|
|
||||||
tempNode2 = null;
|
|
||||||
tempInit = false;
|
|
||||||
|
|
||||||
//not sure why this doesn't happen for centred graphs
|
|
||||||
if (!centred) {
|
|
||||||
$('#topic_addSynapse').val("false");
|
|
||||||
$('#topic_topic1id').val(0);
|
|
||||||
$('#topic_topic2id').val(0);
|
|
||||||
}
|
|
||||||
Mconsole.plot();
|
|
||||||
}
|
|
||||||
|
|
||||||
// thanks to http://stackoverflow.com/questions/4338963/
|
|
||||||
// convert-html-character-entities-back-to-regular-text-using-javascript
|
|
||||||
function decodeEntities(desc) {
|
|
||||||
var str, temp = document.createElement('p');
|
|
||||||
temp.innerHTML = desc; //browser handles the entities
|
|
||||||
str = temp.textContent || temp.innerText;
|
|
||||||
temp = null; //delete the element;
|
|
||||||
return str;
|
|
||||||
} //decodeEntities
|
|
|
@ -1,143 +0,0 @@
|
||||||
(function() {
|
|
||||||
var ua = navigator.userAgent,
|
|
||||||
iStuff = ua.match(/iPhone/i) || ua.match(/iPad/i),
|
|
||||||
typeOfCanvas = typeof HTMLCanvasElement,
|
|
||||||
nativeCanvasSupport = (typeOfCanvas == 'object' || typeOfCanvas == 'function'),
|
|
||||||
textSupport = nativeCanvasSupport
|
|
||||||
&& (typeof document.createElement('canvas').getContext('2d').fillText == 'function');
|
|
||||||
//I'm setting this based on the fact that ExCanvas provides text support for IE
|
|
||||||
//and that as of today iPhone/iPad current text support is lame
|
|
||||||
labelType = (!nativeCanvasSupport || (textSupport && !iStuff))? 'Native' : 'HTML';
|
|
||||||
nativeTextSupport = labelType == 'Native';
|
|
||||||
useGradients = nativeCanvasSupport;
|
|
||||||
animate = !(iStuff || !nativeCanvasSupport);
|
|
||||||
})();
|
|
||||||
|
|
||||||
// init custom node type
|
|
||||||
$jit.ForceDirected.Plot.NodeTypes.implement(nodeSettings);
|
|
||||||
//implement an edge type
|
|
||||||
$jit.ForceDirected.Plot.EdgeTypes.implement(edgeSettings);
|
|
||||||
$jit.ForceDirected.Plot.EdgeTypes.implement(edgeSettingsEmbed);
|
|
||||||
// end
|
|
||||||
|
|
||||||
// init custom node type
|
|
||||||
$jit.RGraph.Plot.NodeTypes.implement(nodeSettings);
|
|
||||||
//implement an edge type
|
|
||||||
$jit.RGraph.Plot.EdgeTypes.implement(edgeSettings);
|
|
||||||
// end
|
|
||||||
|
|
||||||
function initialize(type, loadLater, embed){
|
|
||||||
|
|
||||||
if (loadLater == null) {
|
|
||||||
loadlater = false;
|
|
||||||
}
|
|
||||||
if (embed == null) {
|
|
||||||
embed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
viewMode = "graph";
|
|
||||||
gType = type;
|
|
||||||
|
|
||||||
if ( type == "centered") {
|
|
||||||
// init Rgraph
|
|
||||||
Mconsole = new $jit.RGraph(graphSettings(type));
|
|
||||||
}
|
|
||||||
else if ( type == "arranged" || type == "chaotic" ) {
|
|
||||||
// init ForceDirected
|
|
||||||
Mconsole = new $jit.ForceDirected(graphSettings(type, embed));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert("You didn't specify a type!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// load JSON data.
|
|
||||||
if (!loadLater) {
|
|
||||||
Mconsole.busy = true;
|
|
||||||
Mconsole.loadJSON(json);
|
|
||||||
|
|
||||||
// choose how to plot and animate the data onto the screen
|
|
||||||
var chooseAnimate;
|
|
||||||
|
|
||||||
if ( type == "centered") {
|
|
||||||
// compute positions incrementally and animate.
|
|
||||||
//trigger small animation
|
|
||||||
Mconsole.graph.eachNode(function(n) {
|
|
||||||
var pos = n.getPos();
|
|
||||||
pos.setc(-200, -200);
|
|
||||||
});
|
|
||||||
Mconsole.compute('end');
|
|
||||||
|
|
||||||
chooseAnimate = {
|
|
||||||
modes:['polar'],
|
|
||||||
duration: 2000,
|
|
||||||
onComplete: function() {
|
|
||||||
Mconsole.busy = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if ( type == "arranged" ) {
|
|
||||||
// compute positions incrementally and animate.
|
|
||||||
Mconsole.graph.eachNode(function(n) {
|
|
||||||
var pos = n.getPos();
|
|
||||||
pos.setc(0, 0);
|
|
||||||
var newPos = new $jit.Complex();
|
|
||||||
newPos.x = n.data.$xloc;
|
|
||||||
newPos.y = n.data.$yloc;
|
|
||||||
n.setPos(newPos, 'end');
|
|
||||||
});
|
|
||||||
|
|
||||||
chooseAnimate = {
|
|
||||||
modes: ['linear'],
|
|
||||||
transition: $jit.Trans.Quad.easeInOut,
|
|
||||||
duration: 2500,
|
|
||||||
onComplete: function() {
|
|
||||||
Mconsole.busy = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if ( type == "chaotic" ) {
|
|
||||||
// compute positions incrementally and animate.
|
|
||||||
Mconsole.compute();
|
|
||||||
|
|
||||||
chooseAnimate = {
|
|
||||||
modes: ['linear'],
|
|
||||||
transition: $jit.Trans.Elastic.easeOut,
|
|
||||||
duration: 2500,
|
|
||||||
onComplete: function() {
|
|
||||||
Mconsole.busy = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
|
||||||
if ( type == "centered") {
|
|
||||||
Mconsole.fx.animate(chooseAnimate);
|
|
||||||
}
|
|
||||||
else if ( type == "arranged" || type == "chaotic") {
|
|
||||||
Mconsole.animate(chooseAnimate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// prevent touch events on the canvas from default behaviour
|
|
||||||
$("#infovis-canvas").bind('touchstart', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
Mconsole.events.touched = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// prevent touch events on the canvas from default behaviour
|
|
||||||
$("#infovis-canvas").bind('touchmove', function(event) {
|
|
||||||
//touchPanZoomHandler(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
// prevent touch events on the canvas from default behaviour
|
|
||||||
$("#infovis-canvas").bind('touchend touchcancel', function(event) {
|
|
||||||
lastDist = 0;
|
|
||||||
if (!Mconsole.events.touchMoved && !touchDragNode) hideCurrentCard();
|
|
||||||
Mconsole.events.touched = Mconsole.events.touchMoved = false;
|
|
||||||
touchDragNode = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// end
|
|
||||||
}// if not loadLater
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
function authorizeToEdit(obj) {
|
|
||||||
if (userid && (obj.data.$permission == "commons" || obj.data.$userid == userid)) return true;
|
|
||||||
else return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function mk_permission(obj) {
|
|
||||||
if (obj.getData("permission") == "commons") return "co";
|
|
||||||
else if (obj.getData("permission") == "public") return "pu";
|
|
||||||
else if (obj.getData("permission") == "private") return "pr";
|
|
||||||
}
|
|
|
@ -1,439 +0,0 @@
|
||||||
function centerOn(nodeid) {
|
|
||||||
if (!Mconsole.busy) {
|
|
||||||
var node = Mconsole.graph.getNode(nodeid);
|
|
||||||
$('div.index img').attr('src', imgArray[node.getData('metacode')].src);
|
|
||||||
$('div.index .mapName').html(node.name);
|
|
||||||
$(document).attr('title', node.name + ' | Metamaps');
|
|
||||||
window.history.pushState(node.name, "Metamaps", "/topics/" + node.id);
|
|
||||||
Mconsole.onClick(node.id, {
|
|
||||||
hideLabels: false,
|
|
||||||
duration: 1000,
|
|
||||||
onComplete: function () {
|
|
||||||
fetchRelatives(node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function editEdge(edge, e) {
|
|
||||||
//reset so we don't interfere with other edges, but first, save its x and y
|
|
||||||
var myX = $('#edit_synapse').css('left');
|
|
||||||
var myY = $('#edit_synapse').css('top');
|
|
||||||
$('#edit_synapse').remove();
|
|
||||||
|
|
||||||
//so label is missing while editing
|
|
||||||
deselectEdge(edge);
|
|
||||||
|
|
||||||
//create the wrapper around the form elements, including permissions
|
|
||||||
//classes to make best_in_place happy
|
|
||||||
var edit_div = document.createElement('div');
|
|
||||||
edit_div.setAttribute('id', 'edit_synapse');
|
|
||||||
if (authorizeToEdit(edge)) {
|
|
||||||
edit_div.className = 'permission canEdit';
|
|
||||||
edit_div.className += edge.getData('userid') === userid ? ' yourEdge' : '';
|
|
||||||
} else {
|
|
||||||
edit_div.className = 'permission cannotEdit';
|
|
||||||
}
|
|
||||||
$('.main .wrapper').append(edit_div);
|
|
||||||
|
|
||||||
populateEditEdgeForm(edge);
|
|
||||||
|
|
||||||
//drop it in the right spot, activate it
|
|
||||||
$('#edit_synapse').css('position', 'absolute');
|
|
||||||
if (e) {
|
|
||||||
$('#edit_synapse').css('left', e.clientX);
|
|
||||||
$('#edit_synapse').css('top', e.clientY);
|
|
||||||
} else {
|
|
||||||
$('#edit_synapse').css('left', myX);
|
|
||||||
$('#edit_synapse').css('top', myY);
|
|
||||||
}
|
|
||||||
//$('#edit_synapse_name').click(); //required in case name is empty
|
|
||||||
//$('#edit_synapse_name input').focus();
|
|
||||||
$('#edit_synapse').show();
|
|
||||||
|
|
||||||
MetamapsModel.edgecardInUse = edge.data.$id;
|
|
||||||
}
|
|
||||||
|
|
||||||
function populateEditEdgeForm(edge) {
|
|
||||||
add_name_form(edge);
|
|
||||||
add_user_info(edge);
|
|
||||||
add_perms_form(edge);
|
|
||||||
if (authorizeToEdit(edge)) {
|
|
||||||
add_direction_form(edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function add_name_form(edge) {
|
|
||||||
var data_nil = '<span class="gray">Click to add description.</span>';
|
|
||||||
//name editing form
|
|
||||||
$('#edit_synapse').append('<div id="edit_synapse_name"></div>');
|
|
||||||
$('#edit_synapse_name').attr('class', 'best_in_place best_in_place_desc');
|
|
||||||
$('#edit_synapse_name').attr('data-object', 'synapse');
|
|
||||||
$('#edit_synapse_name').attr('data-attribute', 'desc');
|
|
||||||
$('#edit_synapse_name').attr('data-type', 'textarea');
|
|
||||||
$('#edit_synapse_name').attr('data-nil', data_nil);
|
|
||||||
$('#edit_synapse_name').attr('data-url', '/synapses/' + edge.getData("id"));
|
|
||||||
$('#edit_synapse_name').html(edge.getData("desc"));
|
|
||||||
|
|
||||||
//if edge data is blank or just whitespace, populate it with data_nil
|
|
||||||
if ($('#edit_synapse_name').html().trim() == '') {
|
|
||||||
$('#edit_synapse_name').html(data_nil);
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#edit_synapse_name').bind("ajax:success", function () {
|
|
||||||
var desc = $(this).html();
|
|
||||||
if (desc == data_nil) {
|
|
||||||
edge.setData("desc", '');
|
|
||||||
} else {
|
|
||||||
edge.setData("desc", desc);
|
|
||||||
}
|
|
||||||
selectEdge(edge);
|
|
||||||
Mconsole.plot();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function add_user_info(edge) {
|
|
||||||
$('#edit_synapse').append('<div id="edgeUser" class="hoverForTip"><div class="tip">Created by ' + edge.getData("username") + '</div></div>');
|
|
||||||
}
|
|
||||||
|
|
||||||
function add_perms_form(edge) {
|
|
||||||
//permissions - if owner, also allow permission editing
|
|
||||||
$('#edit_synapse').append('<div class="mapPerm ' + mk_permission(edge) + '"></div>');
|
|
||||||
|
|
||||||
// ability to change permission
|
|
||||||
var selectingPermission = false;
|
|
||||||
if (userid == edge.getData('userid')) {
|
|
||||||
$('#edit_synapse.yourEdge .mapPerm').click(function () {
|
|
||||||
if (!selectingPermission) {
|
|
||||||
selectingPermission = true;
|
|
||||||
$(this).addClass('minimize'); // this line flips the drop down arrow to a pull up arrow
|
|
||||||
if ($(this).hasClass('co')) {
|
|
||||||
$(this).append('<ul class="permissionSelect"><li class="public"></li><li class="private"></li></ul>');
|
|
||||||
} else if ($(this).hasClass('pu')) {
|
|
||||||
$(this).append('<ul class="permissionSelect"><li class="commons"></li><li class="private"></li></ul>');
|
|
||||||
} else if ($(this).hasClass('pr')) {
|
|
||||||
$(this).append('<ul class="permissionSelect"><li class="commons"></li><li class="public"></li></ul>');
|
|
||||||
}
|
|
||||||
$('#edit_synapse .permissionSelect li').click(function (event) {
|
|
||||||
selectingPermission = false;
|
|
||||||
var permission = $(this).attr('class');
|
|
||||||
updateSynapsePermission(edge, permission);
|
|
||||||
event.stopPropagation();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectingPermission = false;
|
|
||||||
$(this).removeClass('minimize'); // this line flips the pull up arrow to a drop down arrow
|
|
||||||
$('#edit_synapse .permissionSelect').remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} //add_perms_form
|
|
||||||
|
|
||||||
function add_direction_form(edge) {
|
|
||||||
//directionality checkboxes
|
|
||||||
$('#edit_synapse').append('<input type="checkbox" id="edit_synapse_left">');
|
|
||||||
$('#edit_synapse').append('<label class="left"><</label>');
|
|
||||||
$('#edit_synapse').append('<input type="checkbox" id="edit_synapse_right">');
|
|
||||||
$('#edit_synapse').append('<label class="right">></label>');
|
|
||||||
|
|
||||||
//determine which node is to the left and the right
|
|
||||||
//if directly in a line, top is left
|
|
||||||
if (edge.nodeFrom.pos.x < edge.nodeTo.pos.x ||
|
|
||||||
edge.nodeFrom.pos.x == edge.nodeTo.pos.x &&
|
|
||||||
edge.nodeFrom.pos.y < edge.nodeTo.pos.y) {
|
|
||||||
var left = edge.nodeTo;
|
|
||||||
var right = edge.nodeFrom;
|
|
||||||
} else {
|
|
||||||
var left = edge.nodeFrom;
|
|
||||||
var right = edge.nodeTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* One node is actually on the left onscreen. Call it left, & the other right.
|
|
||||||
* If category is from-to, and that node is first, check the 'right' checkbox.
|
|
||||||
* Else check the 'left' checkbox since the arrow is incoming.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var directionCat = edge.getData('category'); //both, none, from-to
|
|
||||||
if (directionCat == 'from-to') {
|
|
||||||
var from_to = edge.getData('direction');
|
|
||||||
if (from_to[0] == left.id) {
|
|
||||||
//check left checkbox
|
|
||||||
$('#edit_synapse_left').prop('checked', true);
|
|
||||||
} else {
|
|
||||||
//check right checkbox
|
|
||||||
$('#edit_synapse_right').prop('checked', true);
|
|
||||||
}
|
|
||||||
} else if (directionCat == 'both') {
|
|
||||||
//check both checkboxes
|
|
||||||
$('#edit_synapse_left').prop('checked', true);
|
|
||||||
$('#edit_synapse_right').prop('checked', true);
|
|
||||||
}
|
|
||||||
$('#edit_synapse_left, #edit_synapse_right').click(function () {
|
|
||||||
var leftChecked = $('#edit_synapse_left').is(':checked');
|
|
||||||
var rightChecked = $('#edit_synapse_right').is(':checked');
|
|
||||||
|
|
||||||
var dir = edge.getData('direction');
|
|
||||||
var dirCat = 'none';
|
|
||||||
if (leftChecked && rightChecked) {
|
|
||||||
dirCat = 'both';
|
|
||||||
} else if (!leftChecked && rightChecked) {
|
|
||||||
dirCat = 'from-to';
|
|
||||||
dir = [right.id, left.id];
|
|
||||||
} else if (leftChecked && !rightChecked) {
|
|
||||||
dirCat = 'from-to';
|
|
||||||
dir = [left.id, right.id];
|
|
||||||
}
|
|
||||||
$.ajax({
|
|
||||||
'type': 'PUT',
|
|
||||||
'url': '/synapses/' + edge.getData('id'),
|
|
||||||
'data': {
|
|
||||||
synapse: {
|
|
||||||
category: dirCat
|
|
||||||
},
|
|
||||||
node1_id: {
|
|
||||||
node1: dir[0]
|
|
||||||
},
|
|
||||||
node2_id: {
|
|
||||||
node2: dir[1]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'success': function (data) {
|
|
||||||
updateEdgeDisplay(edge, dir, dirCat);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} //add_direction_form
|
|
||||||
|
|
||||||
function updateEdgeDisplay(edge, dir, dirCat) {
|
|
||||||
edge.setData('category', dirCat);
|
|
||||||
edge.setData('direction', dir);
|
|
||||||
|
|
||||||
//render mid arrow
|
|
||||||
//renderEdgeArrows(Mconsole.fx.edgeHelper, edge);
|
|
||||||
Mconsole.plot();
|
|
||||||
}
|
|
||||||
|
|
||||||
function deselectAllEdges() {
|
|
||||||
var l = MetamapsModel.selectedEdges.length;
|
|
||||||
for (var i = l - 1; i >= 0; i -= 1) {
|
|
||||||
var edge = MetamapsModel.selectedEdges[i];
|
|
||||||
deselectEdge(edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function deselectAllNodes() {
|
|
||||||
var l = MetamapsModel.selectedNodes.length;
|
|
||||||
for (var i = l - 1; i >= 0; i -= 1) {
|
|
||||||
var node = MetamapsModel.selectedNodes[i];
|
|
||||||
deselectNode(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is for hiding one topic from your canvas
|
|
||||||
function removeEdge(edge) {
|
|
||||||
var id = edge.getData("id");
|
|
||||||
$.ajax({
|
|
||||||
type: "DELETE",
|
|
||||||
url: "/synapses/" + id,
|
|
||||||
success: function () {
|
|
||||||
hideEdge(edge);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideEdge(edge) {
|
|
||||||
var from = edge.nodeFrom.id;
|
|
||||||
var to = edge.nodeTo.id;
|
|
||||||
edge.setData('alpha', 0, 'end');
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['edge-property:alpha'],
|
|
||||||
duration: 1000
|
|
||||||
});
|
|
||||||
Mconsole.graph.removeAdjacence(from, to);
|
|
||||||
Mconsole.plot();
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideSelectedEdges() {
|
|
||||||
var l = MetamapsModel.selectedEdges.length;
|
|
||||||
for (var i = l - 1; i >= 0; i -= 1) {
|
|
||||||
var edge = MetamapsModel.selectedEdges[i];
|
|
||||||
hideEdge(edge);
|
|
||||||
}
|
|
||||||
MetamapsModel.selectedEdges = new Array();
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeSelectedEdges() {
|
|
||||||
var l = MetamapsModel.selectedEdges.length;
|
|
||||||
for (var i = l - 1; i >= 0; i -= 1) {
|
|
||||||
if (mapid != null) {
|
|
||||||
var edge = MetamapsModel.selectedEdges[i];
|
|
||||||
var id = edge.getData("id");
|
|
||||||
//delete mapping of id mapid
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: "/synapses/" + mapid + "/" + id + "/removefrommap",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
hideEdge(edge);
|
|
||||||
}
|
|
||||||
MetamapsModel.selectedEdges = new Array();
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteSelectedEdges() {
|
|
||||||
var l = MetamapsModel.selectedEdges.length;
|
|
||||||
for (var i = l - 1; i >= 0; i -= 1) {
|
|
||||||
var edge = MetamapsModel.selectedEdges[i];
|
|
||||||
var id = edge.getData("id");
|
|
||||||
$.ajax({
|
|
||||||
type: "DELETE",
|
|
||||||
url: "/synapses/" + id,
|
|
||||||
});
|
|
||||||
hideEdge(edge);
|
|
||||||
}
|
|
||||||
MetamapsModel.selectedEdges = new Array();
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectNode(node) {
|
|
||||||
if (MetamapsModel.selectedNodes.indexOf(node) != -1) return;
|
|
||||||
node.selected = true;
|
|
||||||
node.setData('dim', 30, 'current');
|
|
||||||
node.setData('whiteCircle', true);
|
|
||||||
node.eachAdjacency(function (adj) {
|
|
||||||
selectEdge(adj);
|
|
||||||
});
|
|
||||||
MetamapsModel.selectedNodes.push(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
function deselectNode(node) {
|
|
||||||
delete node.selected;
|
|
||||||
node.setData('whiteCircle', false);
|
|
||||||
node.eachAdjacency(function (adj) {
|
|
||||||
deselectEdge(adj);
|
|
||||||
});
|
|
||||||
node.setData('dim', 25, 'current');
|
|
||||||
|
|
||||||
//remove the node
|
|
||||||
MetamapsModel.selectedNodes.splice(
|
|
||||||
MetamapsModel.selectedNodes.indexOf(node), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectEdge(edge) {
|
|
||||||
if (MetamapsModel.selectedEdges.indexOf(edge) != -1) return;
|
|
||||||
edge.setData('showDesc', true, 'current');
|
|
||||||
if (!MetamapsModel.embed) {
|
|
||||||
edge.setDataset('end', {
|
|
||||||
lineWidth: 4,
|
|
||||||
color: '#FFFFFF',
|
|
||||||
alpha: 1
|
|
||||||
});
|
|
||||||
} else if (MetamapsModel.embed) {
|
|
||||||
edge.setDataset('end', {
|
|
||||||
lineWidth: 4,
|
|
||||||
color: '#999',
|
|
||||||
alpha: 1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['edge-property:lineWidth:color:alpha'],
|
|
||||||
duration: 100
|
|
||||||
});
|
|
||||||
MetamapsModel.selectedEdges.push(edge);
|
|
||||||
}
|
|
||||||
|
|
||||||
function deselectEdge(edge) {
|
|
||||||
edge.setData('showDesc', false, 'current');
|
|
||||||
edge.setDataset('end', {
|
|
||||||
lineWidth: 2,
|
|
||||||
color: '#222222',
|
|
||||||
alpha: 0.4
|
|
||||||
});
|
|
||||||
|
|
||||||
if (MetamapsModel.edgeHoveringOver == edge) {
|
|
||||||
edge.setData('showDesc', true, 'current');
|
|
||||||
edge.setDataset('end', {
|
|
||||||
lineWidth: 4,
|
|
||||||
color: '#222222',
|
|
||||||
alpha: 1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['edge-property:lineWidth:color:alpha'],
|
|
||||||
duration: 100
|
|
||||||
});
|
|
||||||
|
|
||||||
//remove the edge
|
|
||||||
MetamapsModel.selectedEdges.splice(
|
|
||||||
MetamapsModel.selectedEdges.indexOf(edge), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is for hiding one topic from your canvas
|
|
||||||
function hideNode(nodeid) {
|
|
||||||
var node = Mconsole.graph.getNode(nodeid);
|
|
||||||
if (nodeid == Mconsole.root && gType == "centered") {
|
|
||||||
alert("You can't hide this topic, it is the root of your graph.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
deselectNode(node);
|
|
||||||
|
|
||||||
node.setData('alpha', 0, 'end');
|
|
||||||
node.eachAdjacency(function (adj) {
|
|
||||||
adj.setData('alpha', 0, 'end');
|
|
||||||
});
|
|
||||||
Mconsole.fx.animate({
|
|
||||||
modes: ['node-property:alpha',
|
|
||||||
'edge-property:alpha'],
|
|
||||||
duration: 1000
|
|
||||||
});
|
|
||||||
Mconsole.graph.removeNode(nodeid);
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideSelectedNodes() {
|
|
||||||
var l = MetamapsModel.selectedNodes.length;
|
|
||||||
for (var i = l - 1; i >= 0; i -= 1) {
|
|
||||||
var node = MetamapsModel.selectedNodes[i];
|
|
||||||
hideNode(node.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeNode(nodeid) {
|
|
||||||
var node = Mconsole.graph.getNode(nodeid);
|
|
||||||
deselectNode(node);
|
|
||||||
if (mapperm) {
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: "/topics/" + mapid + "/" + nodeid + "/removefrommap",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeSelectedNodes() {
|
|
||||||
if (mapperm) {
|
|
||||||
var l = MetamapsModel.selectedNodes.length;
|
|
||||||
for (var i = l - 1; i >= 0; i -= 1) {
|
|
||||||
var node = MetamapsModel.selectedNodes[i];
|
|
||||||
removeNode(node.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteNode(nodeid) {
|
|
||||||
if (nodeid == Mconsole.root && gType == "centered") {
|
|
||||||
alert("You can't delete this topic, it is the root of your graph.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$.ajax({
|
|
||||||
type: "DELETE",
|
|
||||||
url: "/topics/" + nodeid,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteSelectedNodes() {
|
|
||||||
var l = MetamapsModel.selectedNodes.length;
|
|
||||||
for (var i = l - 1; i >= 0; i -= 1) {
|
|
||||||
var node = MetamapsModel.selectedNodes[i];
|
|
||||||
deleteNode(node.id);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,213 +0,0 @@
|
||||||
/*
|
|
||||||
* @file
|
|
||||||
* There is a lot of code that goes into creating the "label" of a node
|
|
||||||
* This includes editable cards with all node details, and some controls
|
|
||||||
* onCreateLabelHandler is the main function of this file, and the file
|
|
||||||
* also contains a bunch of helper functions
|
|
||||||
*
|
|
||||||
* html and littleHTML are potentially confusing variables
|
|
||||||
* html is the contents of the card shown when you click on a node's label.
|
|
||||||
* littleHTML creates little controls for removing/hiding nodes from the canvas
|
|
||||||
*
|
|
||||||
* This function features PHP-style variable substitution because the strings
|
|
||||||
* are so damn long. Values are identified by $_id_$, and then a regular
|
|
||||||
* expression is substituted in later (for html, in a separate function).
|
|
||||||
*/
|
|
||||||
|
|
||||||
function buildCardWithHogan(node) {
|
|
||||||
var nodeValues = {};
|
|
||||||
var authorized = authorizeToEdit(node);
|
|
||||||
|
|
||||||
//link is rendered differently if user is logged out or in
|
|
||||||
var go_link, a_tag, close_a_tag;
|
|
||||||
if (!authorized) {
|
|
||||||
go_link = '';
|
|
||||||
if (node.getData("link") != "") {
|
|
||||||
a_tag = '<a href="' + node.getData("link") + '" target="_blank">';
|
|
||||||
close_a_tag = '</a>';
|
|
||||||
} else {
|
|
||||||
a_tag = '';
|
|
||||||
close_a_tag = '';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
go_link = '<a href="' + node.getData("link") + '" ' +
|
|
||||||
' class="go-link" target="_blank"></a>';
|
|
||||||
a_tag = '';
|
|
||||||
close_a_tag = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
var desc_nil = "Click to add description...";
|
|
||||||
var link_nil = "Click to add link...";
|
|
||||||
|
|
||||||
nodeValues.permission = node.getData("permission");
|
|
||||||
nodeValues.mk_permission = mk_permission(node);
|
|
||||||
nodeValues.map_count = node.getData("inmaps").length;
|
|
||||||
nodeValues.synapse_count = node.getData("synapseCount");
|
|
||||||
nodeValues.id = node.id;
|
|
||||||
nodeValues.metacode = node.getData("metacode");
|
|
||||||
nodeValues.metacode_class = 'mbg' + node.getData("metacode").replace(/\s/g, '');
|
|
||||||
nodeValues.imgsrc = imgArray[node.getData("metacode")].src;
|
|
||||||
nodeValues.name = node.name;
|
|
||||||
nodeValues.userid = node.getData("userid");
|
|
||||||
nodeValues.username = node.getData("username");
|
|
||||||
nodeValues.date = node.getData("date");
|
|
||||||
|
|
||||||
// the code for this is stored in /views/main/_metacodeOptions.html.erb
|
|
||||||
nodeValues.metacode_select = $('#metacodeOptions').html();
|
|
||||||
nodeValues.go_link = go_link;
|
|
||||||
nodeValues.a_tag = a_tag;
|
|
||||||
nodeValues.close_a_tag = close_a_tag;
|
|
||||||
nodeValues.link_nil = link_nil;
|
|
||||||
nodeValues.link = (node.getData("link") == "" && authorized) ? link_nil : node.getData("link");
|
|
||||||
nodeValues.desc_nil = desc_nil;
|
|
||||||
nodeValues.desc = (node.getData("desc") == "" && authorized) ? desc_nil : node.getData("desc");
|
|
||||||
|
|
||||||
// the code for the template is stored in /views/layouts/_templates.html.erb
|
|
||||||
var hoganTemplate = Hogan.compile($('#topicCardTemplate').html());
|
|
||||||
return hoganTemplate.render(nodeValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideCurrentCard() {
|
|
||||||
if (MetamapsModel.showcardInUse) {
|
|
||||||
var node = Mconsole.graph.getNode(MetamapsModel.showcardInUse);
|
|
||||||
hideCard(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideCard(node) {
|
|
||||||
var card = '.showcard';
|
|
||||||
|
|
||||||
$(card).fadeOut('fast', function () {
|
|
||||||
//node.setData('dim', 25, 'current');
|
|
||||||
Mconsole.plot();
|
|
||||||
});
|
|
||||||
|
|
||||||
MetamapsModel.showcardInUse = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function populateShowCard(node) {
|
|
||||||
var showCard = document.getElementById('showcard');
|
|
||||||
|
|
||||||
$(showCard).find('.permission').remove();
|
|
||||||
|
|
||||||
var html = buildCardWithHogan(node);
|
|
||||||
|
|
||||||
if (authorizeToEdit(node)) {
|
|
||||||
var perm = document.createElement('div');
|
|
||||||
|
|
||||||
var string = 'permission canEdit';
|
|
||||||
if (userid == node.data.$userid) string += ' yourTopic';
|
|
||||||
perm.className = string;
|
|
||||||
perm.innerHTML = html;
|
|
||||||
showCard.appendChild(perm);
|
|
||||||
} else {
|
|
||||||
var perm = document.createElement('div');
|
|
||||||
perm.className = 'permission cannotEdit';
|
|
||||||
perm.innerHTML = html;
|
|
||||||
showCard.appendChild(perm);
|
|
||||||
}
|
|
||||||
|
|
||||||
var selectingMetacode = false;
|
|
||||||
// attach the listener that shows the metacode title when you hover over the image
|
|
||||||
$('.showcard .metacodeImage').mouseenter(function () {
|
|
||||||
$('.showcard .icon').css('z-index', '4');
|
|
||||||
$('.showcard .metacodeTitle').show();
|
|
||||||
});
|
|
||||||
$('.showcard .linkItem.icon').mouseleave(function () {
|
|
||||||
if (!selectingMetacode) {
|
|
||||||
$('.showcard .metacodeTitle').hide();
|
|
||||||
$('.showcard .icon').css('z-index', '1');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.showcard .metacodeTitle').click(function () {
|
|
||||||
if (!selectingMetacode) {
|
|
||||||
selectingMetacode = true;
|
|
||||||
$(this).addClass('minimize'); // this line flips the drop down arrow to a pull up arrow
|
|
||||||
$('.metacodeSelect').show();
|
|
||||||
// add the scroll bar to the list of metacode select options if it isn't already there
|
|
||||||
if (!$('.metacodeSelect ul').hasClass('mCustomScrollbar')) {
|
|
||||||
$('.metacodeSelect ul').mCustomScrollbar({
|
|
||||||
mouseWheelPixels: 200,
|
|
||||||
advanced: {
|
|
||||||
updateOnContentResize: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.metacodeSelect li').click(function () {
|
|
||||||
selectingMetacode = false;
|
|
||||||
var metacodeName = $(this).find('.mSelectName').text();
|
|
||||||
updateMetacode(node, metacodeName);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
selectingMetacode = false;
|
|
||||||
$(this).removeClass('minimize'); // this line flips the pull up arrow to a drop down arrow
|
|
||||||
$('.metacodeSelect').hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// ability to change permission
|
|
||||||
var selectingPermission = false;
|
|
||||||
if (userid == node.data.$userid) {
|
|
||||||
$('.showcard .yourTopic .mapPerm').click(function () {
|
|
||||||
if (!selectingPermission) {
|
|
||||||
selectingPermission = true;
|
|
||||||
$(this).addClass('minimize'); // this line flips the drop down arrow to a pull up arrow
|
|
||||||
if ($(this).hasClass('co')) {
|
|
||||||
$(this).append('<ul class="permissionSelect"><li class="public"></li><li class="private"></li></ul>');
|
|
||||||
} else if ($(this).hasClass('pu')) {
|
|
||||||
$(this).append('<ul class="permissionSelect"><li class="commons"></li><li class="private"></li></ul>');
|
|
||||||
} else if ($(this).hasClass('pr')) {
|
|
||||||
$(this).append('<ul class="permissionSelect"><li class="commons"></li><li class="public"></li></ul>');
|
|
||||||
}
|
|
||||||
$('.permissionSelect li').click(function (event) {
|
|
||||||
selectingPermission = false;
|
|
||||||
var permission = $(this).attr('class');
|
|
||||||
updateTopicPermission(node, permission);
|
|
||||||
event.stopPropagation();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectingPermission = false;
|
|
||||||
$(this).removeClass('minimize'); // this line flips the pull up arrow to a drop down arrow
|
|
||||||
$('.permissionSelect').remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// when you're typing a description, resize the scroll box to have space
|
|
||||||
$('.best_in_place_desc textarea').bind('keyup', function () {
|
|
||||||
var s = $('.showcard').find('.scroll');
|
|
||||||
s.height(s.height()).mCustomScrollbar('update');
|
|
||||||
console.log('working');
|
|
||||||
});
|
|
||||||
|
|
||||||
//bind best_in_place ajax callbacks
|
|
||||||
$(showCard).find('.best_in_place_name').bind("ajax:success", function () {
|
|
||||||
|
|
||||||
var s = $('.showcard').find('.scroll');
|
|
||||||
s.height(s.height()).mCustomScrollbar('update');
|
|
||||||
|
|
||||||
var name = $(this).html();
|
|
||||||
node.name = decodeEntities(name);
|
|
||||||
Mconsole.plot();
|
|
||||||
});
|
|
||||||
|
|
||||||
$(showCard).find('.best_in_place_desc').bind("ajax:success", function () {
|
|
||||||
this.innerHTML = this.innerHTML.replace(/\r/g, '')
|
|
||||||
|
|
||||||
var s = $('.showcard').find('.scroll');
|
|
||||||
s.height(s.height()).mCustomScrollbar('update');
|
|
||||||
|
|
||||||
var desc = $(this).html();
|
|
||||||
node.setData("desc", desc);
|
|
||||||
});
|
|
||||||
|
|
||||||
$(showCard).find('.best_in_place_link').bind("ajax:success", function () {
|
|
||||||
var link = $(this).html();
|
|
||||||
$(showCard).find('.go-link').attr('href', link);
|
|
||||||
node.setData("link", link);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
|
@ -10,386 +10,12 @@
|
||||||
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
||||||
// GO AFTER THE REQUIRES BELOW.
|
// GO AFTER THE REQUIRES BELOW.
|
||||||
//
|
//
|
||||||
// require autocomplete-rails-uncompressed
|
|
||||||
//
|
|
||||||
//= require jquery
|
//= require jquery
|
||||||
//= require jquery-ui
|
//= require jquery-ui
|
||||||
//= require jquery.purr
|
|
||||||
//= require jquery.lettering
|
|
||||||
//= require jquery.textillate
|
|
||||||
//= require jquery.roundabout.min
|
|
||||||
//= require bip
|
|
||||||
//= require jquery_ujs
|
//= require jquery_ujs
|
||||||
//= require_tree .
|
//= require ./orderedLibraries/underscore
|
||||||
|
//= require ./orderedLibraries/backbone
|
||||||
// other options are 'graph'
|
//= require_directory ./librariesForAllPages
|
||||||
var viewMode = "list";
|
//= require ./metamaps/Metamaps.GlobalUI
|
||||||
|
//= require ./metamaps/Metamaps.Router
|
||||||
var labelType, useGradients, nativeTextSupport, animate, json, Mconsole = null,
|
//= require ./metamaps/Metamaps.Backbone
|
||||||
gType, tempNode = null,
|
|
||||||
tempInit = false,
|
|
||||||
tempNode2 = null,
|
|
||||||
metacodeIMGinit = false,
|
|
||||||
goRealtime = false,
|
|
||||||
mapid = null,
|
|
||||||
mapperm = false,
|
|
||||||
touchPos, touchDragNode, mouseIsDown = false;
|
|
||||||
|
|
||||||
|
|
||||||
// this is to save the layout of a map
|
|
||||||
function saveLayoutAll() {
|
|
||||||
$('.sidebarSave .tip').html('Saving...');
|
|
||||||
var coor = "";
|
|
||||||
if (gType == "arranged" || gType == "chaotic") {
|
|
||||||
Mconsole.graph.eachNode(function (n) {
|
|
||||||
coor = coor + n.getData("mappingid") + '/' + n.pos.x + '/' + n.pos.y + ',';
|
|
||||||
});
|
|
||||||
coor = coor.slice(0, -1);
|
|
||||||
$('#map_coordinates').val(coor);
|
|
||||||
$('#saveMapLayout').submit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is to update the location coordinate of a single node on a map
|
|
||||||
function saveLayout(id) {
|
|
||||||
var n = Mconsole.graph.getNode(id);
|
|
||||||
$('#map_coordinates').val(n.getData("mappingid") + '/' + n.pos.x + '/' + n.pos.y);
|
|
||||||
$('#saveMapLayout').submit();
|
|
||||||
dragged = 0;
|
|
||||||
//$('.wandSaveLayout').html('Saved!');
|
|
||||||
//setTimeout(function(){$('.wandSaveLayout').html('Save Layout')},1500);
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is to save your console to a map
|
|
||||||
function saveToMap() {
|
|
||||||
var nodes_data = "",
|
|
||||||
synapses_data = "";
|
|
||||||
var synapses_array = new Array();
|
|
||||||
Mconsole.graph.eachNode(function (n) {
|
|
||||||
//don't add to the map if it was filtered out
|
|
||||||
if (categoryVisible[n.getData('metacode')] == false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var x, y;
|
|
||||||
if (n.pos.x && n.pos.y) {
|
|
||||||
x = n.pos.x;
|
|
||||||
y = n.pos.y;
|
|
||||||
} else {
|
|
||||||
var x = Math.cos(n.pos.theta) * n.pos.rho;
|
|
||||||
var y = Math.sin(n.pos.theta) * n.pos.rho;
|
|
||||||
}
|
|
||||||
nodes_data += n.id + '/' + x + '/' + y + ',';
|
|
||||||
n.eachAdjacency(function (adj) {
|
|
||||||
synapses_array.push(adj.getData("id"));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//get unique values only
|
|
||||||
synapses_array = $.grep(synapses_array, function (value, key) {
|
|
||||||
return $.inArray(value, synapses_array) === key;
|
|
||||||
});
|
|
||||||
|
|
||||||
synapses_data = synapses_array.join();
|
|
||||||
nodes_data = nodes_data.slice(0, -1);
|
|
||||||
|
|
||||||
$('#map_topicsToMap').val(nodes_data);
|
|
||||||
$('#map_synapsesToMap').val(synapses_data);
|
|
||||||
openLightbox('forkmap');
|
|
||||||
}
|
|
||||||
|
|
||||||
function fetchRelatives(node) {
|
|
||||||
var myA = $.ajax({
|
|
||||||
type: "Get",
|
|
||||||
url: "/topics/" + node.id + "?format=json",
|
|
||||||
success: function (data) {
|
|
||||||
if (gType == "centered") {
|
|
||||||
Mconsole.busy = true;
|
|
||||||
Mconsole.op.sum(data, {
|
|
||||||
type: 'fade',
|
|
||||||
duration: 500,
|
|
||||||
hideLabels: false
|
|
||||||
});
|
|
||||||
Mconsole.graph.eachNode(function (n) {
|
|
||||||
n.eachAdjacency(function (a) {
|
|
||||||
if (!a.getData('showDesc')) {
|
|
||||||
a.setData('alpha', 0.4, 'start');
|
|
||||||
a.setData('alpha', 0.4, 'current');
|
|
||||||
a.setData('alpha', 0.4, 'end');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Mconsole.busy = false;
|
|
||||||
} else {
|
|
||||||
Mconsole.op.sum(data, {
|
|
||||||
type: 'nothing',
|
|
||||||
});
|
|
||||||
Mconsole.plot();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
console.log('failed to recenter');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// @param node = JIT node object
|
|
||||||
// @param metacode = STRING like "Idea", "Action", etc.
|
|
||||||
function updateMetacode(node, metacode) {
|
|
||||||
var mdata = {
|
|
||||||
"topic": {
|
|
||||||
"metacode": metacode
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$.ajax({
|
|
||||||
type: "PUT",
|
|
||||||
dataType: 'json',
|
|
||||||
url: "/topics/" + node.id,
|
|
||||||
data: mdata,
|
|
||||||
success: function (data) {
|
|
||||||
$('.CardOnGraph').find('.metacodeTitle').text(metacode)
|
|
||||||
.attr('class', 'metacodeTitle mbg' + metacode.replace(/\s/g, ''));
|
|
||||||
$('.CardOnGraph').find('.metacodeImage').css('background-image', 'url(' + imgArray[metacode].src + ')');
|
|
||||||
node.setData("metacode", metacode);
|
|
||||||
Mconsole.plot();
|
|
||||||
$('.metacodeTitle').removeClass('minimize'); // this line flips the pull up arrow to a drop down arrow
|
|
||||||
$('.metacodeSelect').hide();
|
|
||||||
setTimeout(function () {
|
|
||||||
$('.metacodeTitle').hide();
|
|
||||||
$('.showcard .icon').css('z-index', '1');
|
|
||||||
}, 500);
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
console.log('failed to update metacode');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateTopicPermission(node, permission) {
|
|
||||||
var mdata = {
|
|
||||||
"topic": {
|
|
||||||
"permission": permission
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$.ajax({
|
|
||||||
type: "PUT",
|
|
||||||
dataType: 'json',
|
|
||||||
url: "/topics/" + node.id,
|
|
||||||
data: mdata,
|
|
||||||
success: function (data) {
|
|
||||||
$('.showcard .mapPerm').removeClass('co pu pr minimize').addClass(permission.substring(0, 2));
|
|
||||||
$('.permissionSelect').remove();
|
|
||||||
node.setData("permission", permission);
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
console.log('failed to update permission');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateSynapsePermission(edge, permission) {
|
|
||||||
var mdata = {
|
|
||||||
"synapse": {
|
|
||||||
"permission": permission
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$.ajax({
|
|
||||||
type: "PUT",
|
|
||||||
dataType: 'json',
|
|
||||||
url: "/synapses/" + edge.data.$id,
|
|
||||||
data: mdata,
|
|
||||||
success: function (data) {
|
|
||||||
$('#edit_synapse .mapPerm').removeClass('co pu pr minimize').addClass(permission.substring(0, 2));
|
|
||||||
$('#edit_synapse .permissionSelect').remove();
|
|
||||||
edge.setData("permission", permission);
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
console.log('failed to update permission');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateMapPermission(mapid, permission) {
|
|
||||||
var mdata = {
|
|
||||||
"map": {
|
|
||||||
"permission": permission
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$.ajax({
|
|
||||||
type: "PUT",
|
|
||||||
dataType: 'json',
|
|
||||||
url: "/maps/" + mapid,
|
|
||||||
data: mdata,
|
|
||||||
success: function (data) {
|
|
||||||
$('.mapPermission').removeClass('commons public private minimize').addClass(permission);
|
|
||||||
$('.mapPermission .permissionSelect').remove();
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
console.log('failed to update permission');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateMetacodeSet(set, index, custom) {
|
|
||||||
|
|
||||||
if (custom && MetamapsModel.newSelectedMetacodes.length == 0) {
|
|
||||||
alert('Please select at least one metacode to use!');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var codesToSwitchTo;
|
|
||||||
MetamapsModel.selectedMetacodeSetIndex = index;
|
|
||||||
MetamapsModel.selectedMetacodeSet = "metacodeset-" + set;
|
|
||||||
|
|
||||||
if (!custom) {
|
|
||||||
codesToSwitchTo = $('#metacodeSwitchTabs' + set).attr('data-metacodes').split(',');
|
|
||||||
$('.customMetacodeList li').addClass('toggledOff');
|
|
||||||
MetamapsModel.selectedMetacodes = [];
|
|
||||||
MetamapsModel.selectedMetacodeNames = [];
|
|
||||||
MetamapsModel.newSelectedMetacodes = [];
|
|
||||||
MetamapsModel.newSelectedMetacodeNames = [];
|
|
||||||
}
|
|
||||||
if (custom) {
|
|
||||||
// uses .slice to avoid setting the two arrays to the same actual array
|
|
||||||
MetamapsModel.selectedMetacodes = MetamapsModel.newSelectedMetacodes.slice(0);
|
|
||||||
MetamapsModel.selectedMetacodeNames = MetamapsModel.newSelectedMetacodeNames.slice(0);
|
|
||||||
codesToSwitchTo = MetamapsModel.selectedMetacodeNames.slice(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort by name
|
|
||||||
codesToSwitchTo.sort();
|
|
||||||
codesToSwitchTo.reverse();
|
|
||||||
|
|
||||||
$('#metacodeImg, #metacodeImgTitle').empty();
|
|
||||||
$('#metacodeImg').removeData('cloudcarousel');
|
|
||||||
var newMetacodes = "";
|
|
||||||
for (var i = 0; i < codesToSwitchTo.length; i++) {
|
|
||||||
newMetacodes += '<img class="cloudcarousel" width="40" height="40" src="' + imgArray[codesToSwitchTo[i]].src + '" title="' + codesToSwitchTo[i] + '" alt="' + codesToSwitchTo[i] + '"/>';
|
|
||||||
};
|
|
||||||
$('#metacodeImg').empty().append(newMetacodes).CloudCarousel({
|
|
||||||
titleBox: $('#metacodeImgTitle'),
|
|
||||||
yRadius: 40,
|
|
||||||
xPos: 150,
|
|
||||||
yPos: 40,
|
|
||||||
speed: 0.3,
|
|
||||||
mouseWheel: true,
|
|
||||||
bringToFront: true
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#lightbox_overlay').hide();
|
|
||||||
$('#topic_name').focus();
|
|
||||||
|
|
||||||
var mdata = {
|
|
||||||
"metacodes": {
|
|
||||||
"value": custom ? MetamapsModel.selectedMetacodes.toString() : MetamapsModel.selectedMetacodeSet
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
dataType: 'json',
|
|
||||||
url: "/user/updatemetacodes",
|
|
||||||
data: mdata,
|
|
||||||
success: function (data) {
|
|
||||||
console.log('selected metacodes saved');
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
console.log('failed to save selected metacodes');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancelMetacodeSetSwitch() {
|
|
||||||
if (MetamapsModel.selectedMetacodeSet != "metacodeset-custom") {
|
|
||||||
$('.customMetacodeList li').addClass('toggledOff');
|
|
||||||
MetamapsModel.selectedMetacodes = [];
|
|
||||||
MetamapsModel.selectedMetacodeNames = [];
|
|
||||||
MetamapsModel.newSelectedMetacodes = [];
|
|
||||||
MetamapsModel.newSelectedMetacodeNames = [];
|
|
||||||
} else { // custom set is selected
|
|
||||||
// reset it to the current actual selection
|
|
||||||
$('.customMetacodeList li').addClass('toggledOff');
|
|
||||||
for (var i = 0; i < MetamapsModel.selectedMetacodes.length; i++) {
|
|
||||||
$('#' + MetamapsModel.selectedMetacodes[i]).removeClass('toggledOff');
|
|
||||||
};
|
|
||||||
// uses .slice to avoid setting the two arrays to the same actual array
|
|
||||||
MetamapsModel.newSelectedMetacodeNames = MetamapsModel.selectedMetacodeNames.slice(0);
|
|
||||||
MetamapsModel.newSelectedMetacodes = MetamapsModel.selectedMetacodes.slice(0);
|
|
||||||
}
|
|
||||||
$('#metacodeSwitchTabs').tabs("select", MetamapsModel.selectedMetacodeSetIndex);
|
|
||||||
$('#topic_name').focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
function MconsoleReset() {
|
|
||||||
|
|
||||||
var tX = Mconsole.canvas.translateOffsetX;
|
|
||||||
var tY = Mconsole.canvas.translateOffsetY;
|
|
||||||
Mconsole.canvas.translate(-tX, -tY);
|
|
||||||
|
|
||||||
var mX = Mconsole.canvas.scaleOffsetX;
|
|
||||||
var mY = Mconsole.canvas.scaleOffsetY;
|
|
||||||
Mconsole.canvas.scale((1 / mX), (1 / mY));
|
|
||||||
}
|
|
||||||
|
|
||||||
function openNodeShowcard(node) {
|
|
||||||
//populate the card that's about to show with the right topics data
|
|
||||||
populateShowCard(node);
|
|
||||||
|
|
||||||
$('.showcard').fadeIn('fast');
|
|
||||||
var s = $('.showcard').find('.scroll');
|
|
||||||
s.height(s.height()).mCustomScrollbar({
|
|
||||||
mouseWheelPixels: 200,
|
|
||||||
advanced: {
|
|
||||||
updateOnContentResize: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
MetamapsModel.showcardInUse = node.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
function openLightbox(which) {
|
|
||||||
$('.lightboxContent').hide();
|
|
||||||
$('#' + which).show();
|
|
||||||
|
|
||||||
$('#lightbox_overlay').show();
|
|
||||||
$('#lightbox_main').css('margin-top', '-' + ($('#lightbox_main').height() / 2) + 'px');
|
|
||||||
|
|
||||||
if (!MetamapsModel.metacodeScrollerInit) {
|
|
||||||
$('.customMetacodeList, .metacodeSetList').mCustomScrollbar({
|
|
||||||
mouseWheelPixels: 200,
|
|
||||||
advanced: {
|
|
||||||
updateOnContentResize: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
MetamapsModel.metacodeScrollerInit = true;
|
|
||||||
}
|
|
||||||
if (which == "switchMetacodes") {
|
|
||||||
MetamapsModel.isSwitchingSet = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeLightbox() {
|
|
||||||
$('#lightbox_overlay').hide();
|
|
||||||
cancelMapCreate('fork_map');
|
|
||||||
cancelMapCreate('new_map');
|
|
||||||
if (MetamapsModel.isSwitchingSet) {
|
|
||||||
cancelMetacodeSetSwitch();
|
|
||||||
MetamapsModel.isSwitchingSet = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancelMapCreate(id) {
|
|
||||||
|
|
||||||
var form = $('#' + id);
|
|
||||||
|
|
||||||
form.find('#map_name').val('');
|
|
||||||
form.find('#map_desc').val('');
|
|
||||||
form.find('#map_permission').val('commons');
|
|
||||||
|
|
||||||
if (id == "fork_map") {
|
|
||||||
form.find('#map_topicsToMap').val('0');
|
|
||||||
form.find('#map_synapsesToMap').val('0');
|
|
||||||
}
|
|
||||||
form.find('.mapPermIcon').removeClass('selected');
|
|
||||||
form.find('.mapCommonsIcon').addClass('selected');
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
20
app/assets/javascripts/compileMapPages.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// This is a manifest file that'll be compiled into map.js, which will include all the files
|
||||||
|
// listed below.
|
||||||
|
//
|
||||||
|
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
||||||
|
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
||||||
|
//
|
||||||
|
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
||||||
|
// the compiled file.
|
||||||
|
//
|
||||||
|
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
||||||
|
// GO AFTER THE REQUIRES BELOW.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// can't use require directory because underscore needs to come before backbone
|
||||||
|
//
|
||||||
|
//= require ./librariesForMapPages/cloudcarousel
|
||||||
|
//= require ./librariesForMapPages/socket.io
|
||||||
|
//= require ./metamaps/JIT
|
||||||
|
//= require ./metamaps/Metamaps
|
||||||
|
//= require ./metamaps/Metamaps.JIT
|
98
app/assets/javascripts/jquery/AllMappingPages.js
vendored
|
@ -1,98 +0,0 @@
|
||||||
/* AllMappingPages means:
|
|
||||||
1. being logged in or logged out and,
|
|
||||||
2. either
|
|
||||||
a. being on a Map page, or
|
|
||||||
b. being on a Topic page
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
|
||||||
|
|
||||||
// initialize topic card draggability and resizability
|
|
||||||
$('.showcard').draggable({
|
|
||||||
handle: ".metacodeImage"
|
|
||||||
});
|
|
||||||
$('#showcard').resizable({
|
|
||||||
maxHeight: 500,
|
|
||||||
maxWidth: 500,
|
|
||||||
minHeight: 320,
|
|
||||||
minWidth: 226,
|
|
||||||
resize: function (event, ui) {
|
|
||||||
var p = $('#showcard').find('.scroll');
|
|
||||||
p.height(p.height()).mCustomScrollbar('update');
|
|
||||||
}
|
|
||||||
}).css({
|
|
||||||
display: 'none',
|
|
||||||
top: '300px',
|
|
||||||
left: '100px'
|
|
||||||
});
|
|
||||||
|
|
||||||
function bindFilterHover() {
|
|
||||||
|
|
||||||
var filterIsOpen = false;
|
|
||||||
|
|
||||||
// controls the sliding hover of the bottom left menu
|
|
||||||
var sliding1 = false;
|
|
||||||
var lT;
|
|
||||||
|
|
||||||
var closeFilter = function () {
|
|
||||||
lT = setTimeout(function () {
|
|
||||||
if (!sliding1) {
|
|
||||||
sliding1 = true;
|
|
||||||
$('.sidebarFilterIcon').css('background-color', '#0F1519');
|
|
||||||
$('.sidebarFilterBox').fadeOut(200, function () {
|
|
||||||
sliding1 = false;
|
|
||||||
filterIsOpen = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
var openFilter = function () {
|
|
||||||
clearTimeout(lT);
|
|
||||||
if (!sliding1) {
|
|
||||||
sliding1 = true;
|
|
||||||
|
|
||||||
// hide the other two
|
|
||||||
$('.sidebarAccountBox').hide();
|
|
||||||
$('.sidebarCollaborateBox').hide();
|
|
||||||
$('.sidebarAccountIcon').css('background-color', '#0F1519');
|
|
||||||
$('.sidebarCollaborateIcon').css('background-color', '#0F1519');
|
|
||||||
|
|
||||||
$('.sidebarFilterIcon').css('background-color', '#000');
|
|
||||||
$('.sidebarFilterBox').fadeIn(200, function () {
|
|
||||||
sliding1 = false;
|
|
||||||
filterIsOpen = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// bind the hover events
|
|
||||||
$(".sidebarFilter").hover(openFilter, closeFilter);
|
|
||||||
|
|
||||||
} // end bindFilterHover
|
|
||||||
|
|
||||||
bindFilterHover();
|
|
||||||
|
|
||||||
// initialize scroll bar for filter by metacode, then hide it and position it correctly again
|
|
||||||
$("#filter_by_metacode").mCustomScrollbar({
|
|
||||||
mouseWheelPixels: 200,
|
|
||||||
advanced: {
|
|
||||||
updateOnContentResize: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$('.sidebarFilterBox').hide().css({
|
|
||||||
position: 'absolute',
|
|
||||||
top: '35px',
|
|
||||||
right: '-36px'
|
|
||||||
});
|
|
||||||
|
|
||||||
// prevent right clicks on the main canvas, so as to not get in the way of our right clicks
|
|
||||||
$('#center-container').bind('contextmenu', function (e) {
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// tab the cheatsheet
|
|
||||||
$('#cheatSheet').tabs().addClass("ui-tabs-vertical ui-helper-clearfix");
|
|
||||||
$("#cheatSheet .ui-tabs-nav li").removeClass("ui-corner-top").addClass("ui-corner-left");
|
|
||||||
}); // end document.ready
|
|
|
@ -1,19 +0,0 @@
|
||||||
/* AuthAllMappingPages means:
|
|
||||||
1. being logged in and,
|
|
||||||
2. either
|
|
||||||
a. being on a Map page, or
|
|
||||||
b. being on a Topic page
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
|
||||||
|
|
||||||
$('.sidebarFork').click(function () {
|
|
||||||
saveToMap();
|
|
||||||
});
|
|
||||||
|
|
||||||
// initialize best_in_place editing
|
|
||||||
$('.authenticated div.permission.canEdit .best_in_place').best_in_place();
|
|
||||||
|
|
||||||
}); // end document.ready
|
|
|
@ -1,97 +0,0 @@
|
||||||
/* authCanEditMapPage means:
|
|
||||||
1. being logged in and,
|
|
||||||
2. being on a Map page and having edit permissions (your map, or commons map)
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
|
||||||
|
|
||||||
function bindRealtimeHover() {
|
|
||||||
|
|
||||||
var realtimeIsOpen = false
|
|
||||||
|
|
||||||
// controls the sliding hover of the bottom left menu
|
|
||||||
var sliding1 = false;
|
|
||||||
var lT;
|
|
||||||
|
|
||||||
var closeRealtime = function () {
|
|
||||||
lT = setTimeout(function () {
|
|
||||||
if (!sliding1) {
|
|
||||||
sliding1 = true;
|
|
||||||
$('.sidebarCollaborateIcon').css('background-color', '#0F1519');
|
|
||||||
$('.sidebarCollaborateBox').fadeOut(200, function () {
|
|
||||||
sliding1 = false;
|
|
||||||
realtimeIsOpen = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
var openRealtime = function () {
|
|
||||||
clearTimeout(lT);
|
|
||||||
if (!sliding1) {
|
|
||||||
sliding1 = true;
|
|
||||||
|
|
||||||
// hide the other two
|
|
||||||
$('.sidebarFilterBox').hide();
|
|
||||||
$('.sidebarAccountBox').hide();
|
|
||||||
$('.sidebarFilterIcon').css('background-color', '#0F1519');
|
|
||||||
$('.sidebarAccountIcon').css('background-color', '#0F1519');
|
|
||||||
|
|
||||||
$('.sidebarCollaborateIcon').css('background-color', '#000');
|
|
||||||
$('.sidebarCollaborateBox').fadeIn(200, function () {
|
|
||||||
sliding1 = false;
|
|
||||||
realtimeIsOpen = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// bind the hover events
|
|
||||||
$(".sidebarCollaborate").hover(openRealtime, closeRealtime);
|
|
||||||
} // end bindRealtimeHover
|
|
||||||
|
|
||||||
function bindSaveHover() {
|
|
||||||
var closeSave = function () {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var openSave = function () {
|
|
||||||
// hide the other three
|
|
||||||
$('.sidebarFilterBox, .sidebarAccountBox, .sidebarCollaborateBox').hide();
|
|
||||||
$('.sidebarFilterIcon, .sidebarAccountIcon, .sidebarCollaborateIcon').css('background-color', '#0F1519');
|
|
||||||
}
|
|
||||||
// bind the hover events
|
|
||||||
$(".sidebarSave").hover(openSave, closeSave);
|
|
||||||
} // end bindSaveHover
|
|
||||||
|
|
||||||
// bind hover events
|
|
||||||
bindRealtimeHover();
|
|
||||||
bindSaveHover();
|
|
||||||
|
|
||||||
// because anyone who can edit the map can collaborate on it in realtime
|
|
||||||
$(".realtimeOnOff").click(function (event) {
|
|
||||||
if (!goRealtime) {
|
|
||||||
window.realtime.sendRealtimeOn();
|
|
||||||
$(this).html('ON').removeClass('rtOff').addClass('rtOn');
|
|
||||||
$(".rtMapperSelf").removeClass('littleRtOff').addClass('littleRtOn');
|
|
||||||
} else {
|
|
||||||
window.realtime.sendRealtimeOff();
|
|
||||||
$(this).html('OFF').removeClass('rtOn').addClass('rtOff');
|
|
||||||
$(".rtMapperSelf").removeClass('littleRtOn').addClass('littleRtOff');
|
|
||||||
}
|
|
||||||
goRealtime = !goRealtime;
|
|
||||||
$(".sidebarCollaborateIcon").toggleClass("blue");
|
|
||||||
});
|
|
||||||
|
|
||||||
// because anyone who can edit the map can save a new map layout
|
|
||||||
$('.sidebarSave').click(function () {
|
|
||||||
saveLayoutAll();
|
|
||||||
});
|
|
||||||
|
|
||||||
// because anyone who can edit the map can change the map title
|
|
||||||
$('.mapInfoName .best_in_place_name').bind("ajax:success", function () {
|
|
||||||
var name = $(this).html();
|
|
||||||
$('.mapName').html(name);
|
|
||||||
});
|
|
||||||
|
|
||||||
}); // end document.ready
|
|
|
@ -1,176 +0,0 @@
|
||||||
/* authCanEditMappingPages means:
|
|
||||||
1. being logged in and,
|
|
||||||
2. either
|
|
||||||
a. being on a Map page and having edit permissions (your map, or commons map) or,
|
|
||||||
b. being on a Topic page
|
|
||||||
|
|
||||||
this code adds required jQuery for creating, or pulling in, topics and synapses
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
|
||||||
|
|
||||||
function bindForkHover() {
|
|
||||||
var closeFork = function () {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var openFork = function () {
|
|
||||||
// hide the other three
|
|
||||||
$('.sidebarFilterBox, .sidebarAccountBox, .sidebarCollaborateBox').hide();
|
|
||||||
$('.sidebarFilterIcon, .sidebarAccountIcon, .sidebarCollaborateIcon').css('background-color', '#0F1519');
|
|
||||||
}
|
|
||||||
// bind the hover events
|
|
||||||
$(".sidebarFork").hover(openFork, closeFork);
|
|
||||||
} // end bindForkHover
|
|
||||||
|
|
||||||
// bind hover events
|
|
||||||
bindForkHover();
|
|
||||||
|
|
||||||
//////
|
|
||||||
//////
|
|
||||||
//// TOPIC CREATION
|
|
||||||
|
|
||||||
// initialize the autocomplete results for the metacode spinner
|
|
||||||
$('#topic_name').typeahead([
|
|
||||||
{
|
|
||||||
name: 'topic_autocomplete',
|
|
||||||
limit: 8,
|
|
||||||
template: $('#topicAutocompleteTemplate').html(),
|
|
||||||
remote: {
|
|
||||||
url: '/topics/autocomplete_topic?term=%QUERY'
|
|
||||||
},
|
|
||||||
engine: Hogan
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
var topicTypeahead = false;
|
|
||||||
// tell the autocomplete to submit the form with the topic you clicked on if you pick from the autocomplete
|
|
||||||
$('#topic_name').bind('typeahead:selected', function (event, datum, dataset) {
|
|
||||||
$('#topic_grabTopic').val(datum.id);
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
$('.new_topic').submit();
|
|
||||||
topicTypeahead = true;
|
|
||||||
});
|
|
||||||
$('#topic_name').bind('typeahead:opened', function () {
|
|
||||||
topicTypeahead = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// bind keyboard handlers
|
|
||||||
$('#topic_name').bind('keyup', function (e) {
|
|
||||||
switch (e.which) {
|
|
||||||
case 13:
|
|
||||||
if (!topicTypeahead) $('.new_topic').submit();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// initialize metacode spinner and then hide it
|
|
||||||
$("#metacodeImg").CloudCarousel({
|
|
||||||
titleBox: $('#metacodeImgTitle'),
|
|
||||||
yRadius: 40,
|
|
||||||
xPos: 150,
|
|
||||||
yPos: 40,
|
|
||||||
speed: 0.3,
|
|
||||||
mouseWheel: true,
|
|
||||||
bringToFront: true
|
|
||||||
});
|
|
||||||
$('.new_topic').hide();
|
|
||||||
|
|
||||||
|
|
||||||
//////
|
|
||||||
//////
|
|
||||||
//// SYNAPSE CREATION
|
|
||||||
|
|
||||||
// initialize the autocomplete results for synapse creation
|
|
||||||
$('#synapse_desc').typeahead([
|
|
||||||
{
|
|
||||||
name: 'synapse_autocomplete',
|
|
||||||
template: "<div>{{label}}</div>",
|
|
||||||
remote: {
|
|
||||||
url: '/search/synapses?term=%QUERY'
|
|
||||||
},
|
|
||||||
engine: Hogan
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'existing_synapses',
|
|
||||||
limit: 50,
|
|
||||||
template: $('#synapseAutocompleteTemplate').html(),
|
|
||||||
remote: {
|
|
||||||
url: '/search/synapses',
|
|
||||||
replace: function () {
|
|
||||||
var q = '/search/synapses?topic1id=' + $('#synapse_topic1id').val() + '&topic2id=' + $('#synapse_topic2id').val();
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
engine: Hogan,
|
|
||||||
header: "<h3>Existing Synapses</h3>"
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
var synapseTypeahead = false;
|
|
||||||
// tell the autocomplete to submit the form with the topic you clicked on if you pick from the autocomplete
|
|
||||||
$('#synapse_desc').bind('typeahead:selected', function (event, datum, dataset) {
|
|
||||||
if (datum.id) { // if they clicked on an existing synapse get it
|
|
||||||
$('#synapse_grabSynapse').val(datum.id);
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
$('.new_synapse').submit();
|
|
||||||
synapseTypeahead = true;
|
|
||||||
});
|
|
||||||
$('#synapse_desc').bind('typeahead:opened', function () {
|
|
||||||
synapseTypeahead = false;
|
|
||||||
});
|
|
||||||
// bind keyboard handlers
|
|
||||||
$('#synapse_desc').bind('keyup', function (e) {
|
|
||||||
switch (e.which) {
|
|
||||||
case 13:
|
|
||||||
if (!synapseTypeahead) $('.new_synapse').submit();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
//////
|
|
||||||
//////
|
|
||||||
//// TOPIC AND SYNAPSE CREATION
|
|
||||||
|
|
||||||
// when either form submits, don't leave the page
|
|
||||||
$('.new_topic, .new_synapse').bind('submit', function (event, data) {
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
// disable right click events on the new topic and new synapse input fields
|
|
||||||
$('#new_topic, #new_synapse').bind('contextmenu', function (e) {
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
//////
|
|
||||||
//////
|
|
||||||
//// SWITCHING METACODE SETS
|
|
||||||
|
|
||||||
$('#metacodeSwitchTabs').tabs({
|
|
||||||
selected: MetamapsModel.selectedMetacodeSetIndex
|
|
||||||
}).addClass("ui-tabs-vertical ui-helper-clearfix");
|
|
||||||
$("#metacodeSwitchTabs .ui-tabs-nav li").removeClass("ui-corner-top").addClass("ui-corner-left");
|
|
||||||
$('.customMetacodeList li').click(function () {
|
|
||||||
if ($(this).attr('class') != 'toggledOff') {
|
|
||||||
$(this).addClass('toggledOff');
|
|
||||||
var value_to_remove = $(this).attr('id');
|
|
||||||
var name_to_remove = $(this).attr('data-name');
|
|
||||||
MetamapsModel.newSelectedMetacodes.splice(MetamapsModel.newSelectedMetacodes.indexOf(value_to_remove), 1);
|
|
||||||
MetamapsModel.newSelectedMetacodeNames.splice(MetamapsModel.newSelectedMetacodeNames.indexOf(name_to_remove), 1);
|
|
||||||
} else if ($(this).attr('class') == 'toggledOff') {
|
|
||||||
$(this).removeClass('toggledOff');
|
|
||||||
MetamapsModel.newSelectedMetacodes.push($(this).attr('id'));
|
|
||||||
MetamapsModel.newSelectedMetacodeNames.push($(this).attr('data-name'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}); // end document.ready
|
|
16
app/assets/javascripts/jquery/AuthEveryPage.js
vendored
|
@ -1,16 +0,0 @@
|
||||||
/* authEveryPage means:
|
|
||||||
1. being logged in and on any page on metamaps
|
|
||||||
|
|
||||||
this code adds required jQuery for the create map lightBox that can be used from any page on metamaps
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
|
||||||
|
|
||||||
// bind permission changer events on the createMap form
|
|
||||||
$('.permIcon').click(function () {
|
|
||||||
$(this).siblings('#map_permission').val($(this).attr('data-permission'));
|
|
||||||
$(this).siblings('.permIcon').find('.mapPermIcon').removeClass('selected');
|
|
||||||
$(this).find('.mapPermIcon').addClass('selected');
|
|
||||||
});
|
|
||||||
|
|
||||||
}); // end document.ready
|
|
|
@ -1,36 +0,0 @@
|
||||||
/* AuthMapCreatorMapPage means:
|
|
||||||
1. being on a Map page
|
|
||||||
2. being the original creator of that map
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
|
||||||
|
|
||||||
// ability to change permission of the map
|
|
||||||
var selectingPermission = false;
|
|
||||||
$('.yourMap .mapPermission').click(function () {
|
|
||||||
if (!selectingPermission) {
|
|
||||||
selectingPermission = true;
|
|
||||||
$(this).addClass('minimize'); // this line flips the drop down arrow to a pull up arrow
|
|
||||||
if ($(this).hasClass('commons')) {
|
|
||||||
$(this).append('<ul class="permissionSelect"><li class="public"></li><li class="private"></li></ul>');
|
|
||||||
} else if ($(this).hasClass('public')) {
|
|
||||||
$(this).append('<ul class="permissionSelect"><li class="commons"></li><li class="private"></li></ul>');
|
|
||||||
} else if ($(this).hasClass('private')) {
|
|
||||||
$(this).append('<ul class="permissionSelect"><li class="commons"></li><li class="public"></li></ul>');
|
|
||||||
}
|
|
||||||
$('.mapPermission .permissionSelect li').click(function (event) {
|
|
||||||
selectingPermission = false;
|
|
||||||
var permission = $(this).attr('class');
|
|
||||||
updateMapPermission(mapid, permission);
|
|
||||||
event.stopPropagation();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectingPermission = false;
|
|
||||||
$(this).removeClass('minimize'); // this line flips the pull up arrow to a drop down arrow
|
|
||||||
$('.mapPermission .permissionSelect').remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}); // end document.ready
|
|
426
app/assets/javascripts/jquery/EveryPage.js
vendored
|
@ -1,426 +0,0 @@
|
||||||
// everything in this document.ready function is here because it is needed on every single page on metamaps
|
|
||||||
$(document).ready(function () {
|
|
||||||
|
|
||||||
function bindMainMenuHover() {
|
|
||||||
|
|
||||||
var menuIsOpen = false
|
|
||||||
|
|
||||||
// controls the sliding hover of the bottom left menu
|
|
||||||
var sliding1 = false;
|
|
||||||
var lT;
|
|
||||||
|
|
||||||
var closeMenu = function () {
|
|
||||||
lT = setTimeout(function () {
|
|
||||||
if (!sliding1) {
|
|
||||||
sliding1 = true;
|
|
||||||
// $('.footer .menu').animate({
|
|
||||||
// height: '0px'
|
|
||||||
// }, 300, function() {
|
|
||||||
// sliding1 = false;
|
|
||||||
// menuIsOpen = false;
|
|
||||||
// });
|
|
||||||
$('.footer').css('border-top-right-radius', '5px');
|
|
||||||
$('.logo').animate({
|
|
||||||
'background-position-x': '-10px'
|
|
||||||
}, 200);
|
|
||||||
$('.footer .menu').fadeOut(200, function () {
|
|
||||||
sliding1 = false;
|
|
||||||
menuIsOpen = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
var openMenu = function () {
|
|
||||||
clearTimeout(lT);
|
|
||||||
if (!sliding1) {
|
|
||||||
sliding1 = true;
|
|
||||||
|
|
||||||
// $('.footer .menu').animate({
|
|
||||||
// height: listLength + 'px'
|
|
||||||
// }, 300, function() {
|
|
||||||
// sliding1 = false;
|
|
||||||
// });
|
|
||||||
$('.footer').css('border-top-right-radius', '0');
|
|
||||||
$('.logo').animate({
|
|
||||||
'background-position-x': '-7px'
|
|
||||||
}, 200);
|
|
||||||
$('.footer .menu').fadeIn(200, function () {
|
|
||||||
sliding1 = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// bind the hover events
|
|
||||||
$(".logo").hover(openMenu, closeMenu);
|
|
||||||
|
|
||||||
// when on touch screen, make touching on the logo do what hovering does on desktop
|
|
||||||
$("#mainTitle a").bind('touchend', function (evt) {
|
|
||||||
if (!menuIsOpen) {
|
|
||||||
openMenu();
|
|
||||||
evt.preventDefault();
|
|
||||||
evt.stopPropagation();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function bindSearchHover() {
|
|
||||||
|
|
||||||
var searchIsOpen = false
|
|
||||||
|
|
||||||
// controls the sliding hover of the search
|
|
||||||
var sliding1 = false;
|
|
||||||
var lT;
|
|
||||||
|
|
||||||
var openSearch = function () {
|
|
||||||
clearTimeout(lT);
|
|
||||||
if (!sliding1 && !searchIsOpen) {
|
|
||||||
hideCards();
|
|
||||||
sliding1 = true;
|
|
||||||
$('.sidebarSearch .twitter-typeahead, .sidebarSearch .tt-hint, .sidebarSearchField').animate({
|
|
||||||
width: '200px'
|
|
||||||
}, 200, function () {
|
|
||||||
$('.sidebarSearchField, .sidebarSearch .tt-hint').css({
|
|
||||||
padding: '5px 10px',
|
|
||||||
width: '180px'
|
|
||||||
});
|
|
||||||
$('.sidebarSearchField').focus();
|
|
||||||
sliding1 = false
|
|
||||||
searchIsOpen = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var closeSearch = function (closeAfter, bypass) {
|
|
||||||
lT = setTimeout(function () {
|
|
||||||
if (!sliding1 && searchIsOpen && (bypass || $('.sidebarSearchField').val() == '')) {
|
|
||||||
sliding1 = true;
|
|
||||||
$('.sidebarSearchField, .sidebarSearch .tt-hint').css({
|
|
||||||
padding: '5px 0',
|
|
||||||
width: '200px'
|
|
||||||
});
|
|
||||||
$('.sidebarSearch .twitter-typeahead, .sidebarSearch .tt-hint, .sidebarSearchField').animate({
|
|
||||||
width: '0'
|
|
||||||
}, 200, function () {
|
|
||||||
$('.sidebarSearchField').typeahead('setQuery', '');
|
|
||||||
$('.sidebarSearchField').blur();
|
|
||||||
sliding1 = false;
|
|
||||||
searchIsOpen = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, closeAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind the hover events
|
|
||||||
$(".sidebarSearch").hover(function () {
|
|
||||||
openSearch()
|
|
||||||
}, function () {
|
|
||||||
closeSearch(800, false)
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.sidebarSearchIcon').click(function (e) {
|
|
||||||
$('.sidebarSearchField').focus();
|
|
||||||
});
|
|
||||||
$('.sidebarSearch').click(function (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
});
|
|
||||||
$('body').click(function (e) {
|
|
||||||
closeSearch(0, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
// if the search is closed and user hits ctrl+/
|
|
||||||
// close if they hit ESC
|
|
||||||
$('body').bind('keydown', function (e) {
|
|
||||||
switch (e.which) {
|
|
||||||
case 191:
|
|
||||||
if (e.ctrlKey && !searchIsOpen) {
|
|
||||||
openSearch();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 27:
|
|
||||||
if (searchIsOpen) {
|
|
||||||
closeSearch(0, true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break; //console.log(e.which);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// initialize the search box autocomplete results
|
|
||||||
var mapheader = userid ? '<h3 class="search-header">Maps</h3><input type="checkbox" class="limitToMe" id="limitMapsToMe"></input><label for="limitMapsToMe" class="limitToMeLabel">added by me</label><div class="minimizeResults minimizeMapResults"></div><div class="clearfloat"></div>' : '<h3 class="search-header">Maps</h3><div class="minimizeResults minimizeMapResults"></div><div class="clearfloat"></div>';
|
|
||||||
var topicheader = userid ? '<h3 class="search-header">Topics</h3><input type="checkbox" class="limitToMe" id="limitTopicsToMe"></input><label for="limitTopicsToMe" class="limitToMeLabel">added by me</label><div class="minimizeResults minimizeTopicResults"></div><div class="clearfloat"></div>' : '<h3 class="search-header">Topics</h3><div class="minimizeResults minimizeTopicResults"></div><div class="clearfloat"></div>';
|
|
||||||
$('.sidebarSearchField').typeahead([
|
|
||||||
{
|
|
||||||
name: 'topics',
|
|
||||||
limit: 9999,
|
|
||||||
dupChecker: function (datum1, datum2) {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
template: $('#topicSearchTemplate').html(),
|
|
||||||
remote: {
|
|
||||||
url: '/search/topics?term=%QUERY',
|
|
||||||
replace: function () {
|
|
||||||
var q = '/search/topics?term=' + $('.sidebarSearchField').val();
|
|
||||||
if ($("#limitTopicsToMe").is(':checked')) {
|
|
||||||
q += "&user=" + userid.toString();
|
|
||||||
}
|
|
||||||
return q;
|
|
||||||
},
|
|
||||||
filter: function (dataset) {
|
|
||||||
if (dataset.length == 0) {
|
|
||||||
dataset.push({
|
|
||||||
value: "No results",
|
|
||||||
label: "No results",
|
|
||||||
typeImageURL: "/assets/icons/wildcard.png",
|
|
||||||
rtype: "noresult"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return dataset;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
engine: Hogan,
|
|
||||||
header: topicheader
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'maps',
|
|
||||||
limit: 9999,
|
|
||||||
dupChecker: function (datum1, datum2) {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
template: $('#mapSearchTemplate').html(),
|
|
||||||
remote: {
|
|
||||||
url: '/search/maps?term=%QUERY',
|
|
||||||
replace: function () {
|
|
||||||
var q = '/search/maps?term=' + $('.sidebarSearchField').val();
|
|
||||||
if ($("#limitMapsToMe").is(':checked')) {
|
|
||||||
q += "&user=" + userid.toString();
|
|
||||||
}
|
|
||||||
return q;
|
|
||||||
},
|
|
||||||
filter: function (dataset) {
|
|
||||||
if (dataset.length == 0) {
|
|
||||||
dataset.push({
|
|
||||||
value: "No results",
|
|
||||||
label: "No results",
|
|
||||||
rtype: "noresult"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return dataset;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
engine: Hogan,
|
|
||||||
header: mapheader
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'mappers',
|
|
||||||
limit: 9999,
|
|
||||||
dupChecker: function (datum1, datum2) {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
template: $('#mapperSearchTemplate').html(),
|
|
||||||
remote: {
|
|
||||||
url: '/search/mappers?term=%QUERY',
|
|
||||||
filter: function (dataset) {
|
|
||||||
if (dataset.length == 0) {
|
|
||||||
dataset.push({
|
|
||||||
value: "No results",
|
|
||||||
label: "No results",
|
|
||||||
rtype: "noresult"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return dataset;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
engine: Hogan,
|
|
||||||
header: '<h3 class="search-header">Mappers</h3><div class="minimizeResults minimizeMapperResults"></div><div class="clearfloat"></div>'
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
//Set max height of the search results box to prevent it from covering bottom left footer
|
|
||||||
$('.sidebarSearchField').bind('typeahead:opened', function (event) {
|
|
||||||
var h = $(window).height();
|
|
||||||
$(".tt-dropdown-menu").css('max-height', h - 100);
|
|
||||||
});
|
|
||||||
$(window).resize(function () {
|
|
||||||
var h = $(window).height();
|
|
||||||
$(".tt-dropdown-menu").css('max-height', h - 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// tell the autocomplete to launch a new tab with the topic, map, or mapper you clicked on
|
|
||||||
$('.sidebarSearchField').bind('typeahead:selected', function (event, datum, dataset) {
|
|
||||||
console.log(event);
|
|
||||||
if (datum.rtype != "noresult") {
|
|
||||||
var win;
|
|
||||||
if (dataset == "topics") {
|
|
||||||
win = window.open('/topics/' + datum.id, '_blank');
|
|
||||||
} else if (dataset == "maps") {
|
|
||||||
win = window.open('/maps/' + datum.id, '_blank');
|
|
||||||
} else if (dataset == "mappers") {
|
|
||||||
win = window.open('/maps/mappers/' + datum.id, '_blank');
|
|
||||||
}
|
|
||||||
win.focus();
|
|
||||||
closeSearch(0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var checkboxChangeInit = false,
|
|
||||||
minimizeInit = false;
|
|
||||||
|
|
||||||
$('.sidebarSearchField').bind('keyup', function () {
|
|
||||||
|
|
||||||
// when the user selects 'added by me' resend the query with their userid attached
|
|
||||||
if (!checkboxChangeInit) {
|
|
||||||
$('.limitToMe').bind("change", function (e) {
|
|
||||||
// set the value of the search equal to itself to retrigger the autocomplete event
|
|
||||||
searchIsOpen = false;
|
|
||||||
$('.sidebarSearchField').typeahead('setQuery', $('.sidebarSearchField').val());
|
|
||||||
setTimeout(function () {
|
|
||||||
searchIsOpen = true;
|
|
||||||
}, 2000);
|
|
||||||
});
|
|
||||||
checkboxChangeInit = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when the user clicks minimize section, hide the results for that section
|
|
||||||
if (!minimizeInit) {
|
|
||||||
$('.minimizeMapperResults').click(function (e) {
|
|
||||||
var s = $('.tt-dataset-mappers .tt-suggestions');
|
|
||||||
console.log(s.css('height'));
|
|
||||||
if (s.css('height') == '0px') {
|
|
||||||
$('.tt-dataset-mappers .tt-suggestions').css({
|
|
||||||
'height': 'auto',
|
|
||||||
'overflow': 'visible'
|
|
||||||
});
|
|
||||||
$(this).removeClass('maximizeResults').addClass('minimizeResults');
|
|
||||||
} else {
|
|
||||||
$('.tt-dataset-mappers .tt-suggestions').css({
|
|
||||||
'height': '0',
|
|
||||||
'overflow': 'hidden'
|
|
||||||
});
|
|
||||||
$(this).removeClass('minimizeResults').addClass('maximizeResults');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$('.minimizeTopicResults').click(function (e) {
|
|
||||||
var s = $('.tt-dataset-topics .tt-suggestions');
|
|
||||||
console.log(s.css('height'));
|
|
||||||
if (s.css('height') == '0px') {
|
|
||||||
s.css({
|
|
||||||
'height': 'auto',
|
|
||||||
'border-top': 'none',
|
|
||||||
'overflow': 'visible'
|
|
||||||
});
|
|
||||||
$(this).removeClass('maximizeResults').addClass('minimizeResults');
|
|
||||||
} else {
|
|
||||||
s.css({
|
|
||||||
'height': '0',
|
|
||||||
'border-top': '1px solid rgb(56, 56, 56)',
|
|
||||||
'overflow': 'hidden'
|
|
||||||
});
|
|
||||||
$(this).removeClass('minimizeResults').addClass('maximizeResults');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$('.minimizeMapResults').click(function (e) {
|
|
||||||
var s = $('.tt-dataset-maps .tt-suggestions');
|
|
||||||
console.log(s.css('height'));
|
|
||||||
if (s.css('height') == '0px') {
|
|
||||||
s.css({
|
|
||||||
'height': 'auto',
|
|
||||||
'border-top': 'none',
|
|
||||||
'overflow': 'visible'
|
|
||||||
});
|
|
||||||
$(this).removeClass('maximizeResults').addClass('minimizeResults');
|
|
||||||
} else {
|
|
||||||
s.css({
|
|
||||||
'height': '0',
|
|
||||||
'border-top': '1px solid rgb(56, 56, 56)',
|
|
||||||
'overflow': 'hidden'
|
|
||||||
});
|
|
||||||
$(this).removeClass('minimizeResults').addClass('maximizeResults');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
minimizeInit = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
$('.sidebarSearch button.addToMap').click(function (event) {
|
|
||||||
event.stopPropagation();
|
|
||||||
});
|
|
||||||
} // end bindSearchHover
|
|
||||||
|
|
||||||
function bindAccountHover() {
|
|
||||||
|
|
||||||
var accountIsOpen = false
|
|
||||||
|
|
||||||
// controls the sliding hover of the bottom left menu
|
|
||||||
var sliding1 = false;
|
|
||||||
var lT;
|
|
||||||
|
|
||||||
var closeAccount = function () {
|
|
||||||
lT = setTimeout(function () {
|
|
||||||
if (!sliding1) {
|
|
||||||
sliding1 = true;
|
|
||||||
$('.sidebarAccountIcon').css('background-color', '#0F1519');
|
|
||||||
$('.sidebarAccountBox').fadeOut(200, function () {
|
|
||||||
sliding1 = false;
|
|
||||||
accountIsOpen = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
var openAccount = function () {
|
|
||||||
clearTimeout(lT);
|
|
||||||
if (!sliding1) {
|
|
||||||
sliding1 = true;
|
|
||||||
|
|
||||||
// hide the other two
|
|
||||||
$('.sidebarFilterBox').hide();
|
|
||||||
$('.sidebarCollaborateBox').hide();
|
|
||||||
$('.sidebarFilterIcon').css('background-color', '#0F1519');
|
|
||||||
$('.sidebarCollaborateIcon').css('background-color', '#0F1519');
|
|
||||||
|
|
||||||
$('.sidebarAccountIcon').css('background-color', '#000');
|
|
||||||
$('.sidebarAccountBox').fadeIn(200, function () {
|
|
||||||
sliding1 = false;
|
|
||||||
accountIsOpen = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// bind the hover events
|
|
||||||
$(".sidebarAccount").hover(openAccount, closeAccount);
|
|
||||||
} // end bindAccountHover
|
|
||||||
|
|
||||||
// bind hover events
|
|
||||||
bindMainMenuHover();
|
|
||||||
bindSearchHover();
|
|
||||||
bindAccountHover();
|
|
||||||
|
|
||||||
// hide notices after 10 seconds
|
|
||||||
$('.notice.metamaps').delay(10000).fadeOut('fast');
|
|
||||||
$('.alert.metamaps').delay(10000).fadeOut('fast');
|
|
||||||
|
|
||||||
//bind lightbox clicks
|
|
||||||
$('.openLightbox').click(function (event) {
|
|
||||||
openLightbox($(this).attr('data-open'));
|
|
||||||
event.preventDefault();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// bind keyboard handlers
|
|
||||||
$('body').bind('keyup', function (e) {
|
|
||||||
switch (e.which) {
|
|
||||||
case 13:
|
|
||||||
enterKeyHandler(e);
|
|
||||||
break;
|
|
||||||
case 27:
|
|
||||||
escKeyHandler();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break; //console.log(e.which);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}); // end document.ready
|
|
48
app/assets/javascripts/jquery/MapPage.js
vendored
|
@ -1,48 +0,0 @@
|
||||||
/* MapPage means:
|
|
||||||
1. being on a Map page
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
|
||||||
|
|
||||||
function bindInfoHover() {
|
|
||||||
|
|
||||||
var infoIsOpen = false;
|
|
||||||
|
|
||||||
// controls the sliding hover of the bottom left menu
|
|
||||||
var sliding1 = false;
|
|
||||||
var lT;
|
|
||||||
|
|
||||||
var closeInfo = function () {
|
|
||||||
lT = setTimeout(function () {
|
|
||||||
if (!sliding1) {
|
|
||||||
sliding1 = true;
|
|
||||||
$('.mapInfoBox').fadeOut(200, function () {
|
|
||||||
sliding1 = false;
|
|
||||||
infoIsOpen = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
var openInfo = function (event) {
|
|
||||||
clearTimeout(lT);
|
|
||||||
if (!sliding1 && event.target.className != "openCheatsheet openLightbox") {
|
|
||||||
sliding1 = true;
|
|
||||||
|
|
||||||
$('.mapInfoBox').fadeIn(200, function () {
|
|
||||||
sliding1 = false;
|
|
||||||
infoIsOpen = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// bind the hover events
|
|
||||||
$("div.index").hover(openInfo, closeInfo);
|
|
||||||
|
|
||||||
|
|
||||||
} // end bindInfoHover
|
|
||||||
|
|
||||||
bindInfoHover();
|
|
||||||
|
|
||||||
}); // end document.ready
|
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,71 @@
|
||||||
|
== SoundManager 2: JavaScript Sound for the Web
|
||||||
|
|
||||||
|
By wrapping and extending HTML5 and Flash Audio APIs, SoundManager 2 brings reliable cross-platform audio to JavaScript.
|
||||||
|
|
||||||
|
== HTML5 Audio() Support
|
||||||
|
|
||||||
|
* 100% Flash-free MP3 + MP4/AAC where supported
|
||||||
|
* Compatible with Apple iPad 3.2, iPhone/iOS 4 and newer
|
||||||
|
* Fallback to Flash for MP3/MP4 support, as needed
|
||||||
|
* SM2 API is transparent; HTML5/flash switching handled internally
|
||||||
|
* HTML5 API support approximates Flash 8 API features
|
||||||
|
* Some other formats (WAV/OGG) supported via HTML5, depending on browser
|
||||||
|
* See "useHTML5Audio" property for implementation details
|
||||||
|
|
||||||
|
== Basic API Features (Flash 8)
|
||||||
|
|
||||||
|
* Load, stop, play, pause, mute, seek, pan and volume control of sounds from Javascript
|
||||||
|
* Events: onload, whileloading, whileplaying, onfinish and more
|
||||||
|
* ID3V1 and ID3V2 tag support for MP3s (title, artist, genre etc.)
|
||||||
|
|
||||||
|
== Shiny Flash 9 Features
|
||||||
|
|
||||||
|
* RTMP / Flash Media Server streaming support (new, experimental)
|
||||||
|
* MPEG-4 (AAC, HE-AAC, H.264) audio support
|
||||||
|
* "MultiShot" play (layered/chorusing effects)
|
||||||
|
* Waveform/frequency spectrum data
|
||||||
|
* Peak (L/R channel volume) data
|
||||||
|
* Audio buffering state/event handling
|
||||||
|
|
||||||
|
== General Tech Stuff
|
||||||
|
|
||||||
|
* Full API Documentation with examples and notes
|
||||||
|
* console.log()-style debug output and troubleshooting tools
|
||||||
|
* Community-based discussion/support
|
||||||
|
|
||||||
|
== As Heard On The Internets
|
||||||
|
|
||||||
|
A few nifty sites that have implemented SM2 for driving audio:
|
||||||
|
|
||||||
|
* SoundCloud / The Cloud Player
|
||||||
|
* last.fm
|
||||||
|
* Opera (media player component)
|
||||||
|
* 8tracks
|
||||||
|
* Discogs
|
||||||
|
* The Hype Machine
|
||||||
|
* nyan.cat
|
||||||
|
* turntable.fm
|
||||||
|
* AudioGalaxy
|
||||||
|
|
||||||
|
== Project home, documentation, live demos etc.:
|
||||||
|
|
||||||
|
http://www.schillmania.com/projects/soundmanager2/
|
||||||
|
|
||||||
|
== Compiling JS builds (-nodebug, -jsmin) and Flash components, AS2/AS3 to SWF
|
||||||
|
|
||||||
|
An Ant build file defines the tasks for compiling JS and SWF components, useful if you make changes to the SM2 source and want to recompile.
|
||||||
|
Google's Closure Compiler is used for the JS. AS2 compilation is done by MTASC, and AS3 is handled by Adobe's Open Source Flex SDK (mxmlc) compiler.
|
||||||
|
Refer to the build.xml file for compiler downloads and path definitions.
|
||||||
|
|
||||||
|
== Versioning / Development Notes
|
||||||
|
|
||||||
|
Releases are versioned by date, e.g., V2.97a.20110424 and are tagged as such.*
|
||||||
|
The latest official release is always on trunk/master.
|
||||||
|
Post-release development builds may be available on the appropriate +DEV branch, eg., V2.97a.20110801+DEV
|
||||||
|
|
||||||
|
== Forks and Pull Requests
|
||||||
|
|
||||||
|
Firstly, thank you for wanting to contribute! Bug fixes and tweaks are welcomed, particularly if they follow the general coding style of the project.
|
||||||
|
If making a pull request, use the project's current +DEV development branch as the merge target instead of "master", if possible (please and thank-you.)
|
||||||
|
|
||||||
|
* SoundManager 2 has been at "version" 2.97 for a long time, because 2.97 was arguably the best llama-ass-whipping version of WinAmp. (WinAmp 3 was not as good, and WinAmp 5 was "the best of 2 and 3 combined.") This MP3 player was my favourite Windows app during the 90's, and is missed as there's nothing quite like it on OS X where I spend most of my time these days.
|
After Width: | Height: | Size: 329 B |
After Width: | Height: | Size: 422 B |
After Width: | Height: | Size: 329 B |
After Width: | Height: | Size: 339 B |
After Width: | Height: | Size: 441 B |
After Width: | Height: | Size: 477 B |
After Width: | Height: | Size: 441 B |
After Width: | Height: | Size: 368 B |
After Width: | Height: | Size: 889 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 881 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1,009 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1,001 B |
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,156 @@
|
||||||
|
/* larger canvas, spectrum + EQ visualization and other items */
|
||||||
|
|
||||||
|
.ui360-vis,
|
||||||
|
.ui360-vis .sm2-360ui,
|
||||||
|
.sm2-inline-list .ui360-vis {
|
||||||
|
/* size of the container for the circle, etc. */
|
||||||
|
width:256px;
|
||||||
|
height:256px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360-vis {
|
||||||
|
position:relative;
|
||||||
|
/* a little extra spacing */
|
||||||
|
padding-top:1px;
|
||||||
|
padding-bottom:1px;
|
||||||
|
margin-bottom:-18px; /* approximate "line height" we want */
|
||||||
|
padding-left:248px;
|
||||||
|
margin-left:0px;
|
||||||
|
background-position:22.6% 50%; /* (~109px) initial play button position */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-list .ui360-vis {
|
||||||
|
cursor:pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360-vis a {
|
||||||
|
font:14px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;
|
||||||
|
white-space:nowrap;
|
||||||
|
text-indent:0px; /* undo inline style */
|
||||||
|
top:46%; /* ehh. */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-list .ui360-vis a {
|
||||||
|
line-height:256px;
|
||||||
|
top:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360-vis .sm2-360ui {
|
||||||
|
margin-left:-256px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360-vis .sm2-timing {
|
||||||
|
font:bold 24px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;
|
||||||
|
color:#333;
|
||||||
|
text-align:center;
|
||||||
|
line-height:256px;
|
||||||
|
text-indent:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-list .ui360-vis,
|
||||||
|
.sm2-inline-list .ui360-vis .sm2-360ui {
|
||||||
|
margin-left:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-list .ui360-vis {
|
||||||
|
margin:8px 13px 7px 0px;
|
||||||
|
padding-left:0px;
|
||||||
|
background-position:50% 50%; /* initial play button position */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-list .ui360-vis .sm2-360ui {
|
||||||
|
border:1px solid #eee;
|
||||||
|
/* offset the border */
|
||||||
|
margin-left:-1px;
|
||||||
|
margin-top:-1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-list .ui360-vis a {
|
||||||
|
position:absolute;
|
||||||
|
display:inline;
|
||||||
|
left:0px;
|
||||||
|
bottom:0px;
|
||||||
|
top:1px;
|
||||||
|
width:100%; /* 2px padding in box */
|
||||||
|
height:99%; /* dumb vertical hack */
|
||||||
|
*height:256px; /* IE is dumb. */
|
||||||
|
overflow:hidden;
|
||||||
|
font-size:small;
|
||||||
|
font-weight:300;
|
||||||
|
color:#333;
|
||||||
|
margin:0px;
|
||||||
|
padding:0px;
|
||||||
|
line-height:488px; /* bottom vertical alignment for text */
|
||||||
|
*line-height:480px; /* IE again */
|
||||||
|
text-align:center;
|
||||||
|
border-radius:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-list .ui360 a:hover {
|
||||||
|
background-color:transparent; /* reset */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-list .ui360-vis:hover .sm2-360ui,
|
||||||
|
.sm2-inline-list .ui360-vis a.sm2_link:hover,
|
||||||
|
.sm2-inline-list .ui360-vis a.sm2_link:active,
|
||||||
|
.sm2-inline-list .ui360-vis a.sm2_link:focus {
|
||||||
|
background-color:transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-list .ui360-vis:hover a.sm2_link {
|
||||||
|
background-color:#fafafa;
|
||||||
|
*background-color:transparent; /* eh, screw IE. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use a bigger loading image for this layout */
|
||||||
|
|
||||||
|
.ui360-vis .sm2-360btn,
|
||||||
|
.ui360-vis .sm2-360ui.sm2_paused .sm2-360btn,
|
||||||
|
.ui360-vis .sm2-360ui.sm2_playing .sm2-360btn {
|
||||||
|
width:48px;
|
||||||
|
height:48px;
|
||||||
|
margin-left:-24px;
|
||||||
|
margin-top:-24px;
|
||||||
|
border-radius: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360-vis,
|
||||||
|
.ui360-vis .sm2-360ui.sm2_paused .sm2-360btn,
|
||||||
|
.ui360-vis .sm2-360btn-default {
|
||||||
|
background:transparent url(360-button-vis-play.png) no-repeat 50% 50%;
|
||||||
|
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAABuVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv7++lpaXr6+uAgIDk5OQzMzPt7e1tbW3n5+dgYGDW1tZNTU10dHQ5OTnw8PCvr6/e3t6JiYlAQEDb29vo6OgrKyuqqqrq6uq4uLjf399AQEDGxsbq6uqAgIDY2Nje3t61tbXp6enU1NTu7u7r6+vl5eXt7e2fn5/n5+fDw8Ph4eHv7+/t7e3CwsLW1tbu7u7b29vw8PDm5uYgICDp6enY2Nji4uLo6Ojm5uakpKTS0tLPz8/h4eHw8PDs7Ozj4+Pa2trg4ODx8fHT09Pk5OTPz8/S0tLBwcGmpqawsLCOjo7h4eHn5+fo6OgAAADY2NjNzc3n5+cAAADd3d3Gxsbu7u7t7e0AAADX19fl5eXi4uLf39/Hx8fn5+fs7Ozg4ODR0dHX19e4uLjv7+/z8/P09PTy8vL19fXv7+/n5+fx8fH29vbs7Ozq6urm5ubo6Ojw8PDu7u7p6enr6+sAAAB/f3/Z2dn39/fh4eGOjo4ODg7t7e3l5eWWlpba2tqjo6NVVVXk5OTe3t65ubnMzMzExMTf39/GxsampqZiYmJNcTiZAAAAbXRSTlMAAQIEAwcFCAb5EdAImAXpB6oIUAoLCfsgZQ0EVrsGEr4ZYQgbsgpUYxikNd/aatQQli+R7rlUUdas6+8I+VaFruoOOV/S8Nq5sWL8UqmKUFsuHyTcrtsJm0z7C49V3NMKkdKXuk7S7oVeVSv7tAAEVwAAAu5JREFUeF6llmVz3DwURmNLsr1pmJmZmZmxzMwsybS8gXJfhl9cKXbHEK+TmZ4P/nDnOXN1NbalHD8CQ7QRGDmhnIQhBDYQnkhheRECSVIQQrLMHookAciUkHhBw1zVwuLShcJIpPDC0uJC1VxDQTaFx1srSvM3DUxU1TRVlWBjM7+0opUrQaupLSnrLK7ELIepwaCYmbiyuLOspJY38eeLykdGxzDhYQfKCmOjI+VFPkMQYF7NZD0l2DgFJrR+siYPegxBzBvqeoQxpgGw8qOuoTz3HGw9udUPCaFZIORhdS5blZOHjXWDBIdABusanb0S4MpqEw4XcNPqCrQFQQTN+XwPQ8CY5jcDUbB3KLdlg6hnQDZacqEgWA3a2rF6Jri9zWohwI6dXXK2QHZ3OqBw0qC7B6vnAPd0sxZMkHr7VNPD34YZgNrXK3EBSgPU9HJ4eIQDDDogQS4ow4QJxy4+MmKs4oYJZFhhggjQuMoKHoHzn3bsQx1HQOTClOkXLP6lviZTtjCjmn7B5g/izqszliBHTB+HDhl3PSJbwnxSS3n45HDkVLXkvCWg5Uws7eHgJ98/uKqxzLI9w3o6oXuwhd+OPNVEet0WtnU9/sWNJfz1u6cY1/VtLghQuRgk/PmBmT7hogJPXo3L8YQed3Nw8PWfuB89Eb8scUGUrl33DfH/N93BGeH6NUnkArh1O5FOuNETp2GR27cAE/iaJu6mz8HdCQnan+i96XQmdgaZ9PQ9+xMVoPJgNhrNhBKNzj5Q+E/AavH4SSz6OZRo7Mlj3oDDp7jyPJoKJfr8CpvAOUrQi6eppJaVZOrpCwTdP1cgr93UjKxoN9dka2KX8ealZtBADO3lG2+e7xRAd7Y0igOg2tYdBKD/CBIBenf/lYGJD2y8uv8OgaBDDkry3v57SlQXhL7f35OlwJOXGUBBl571JykmzCIE02T/s0tIASyf/R6Arr59fcM62G+8fnsVhdwFwq4Ov345Of/15wd0RYY81HHUTQAAAABJRU5ErkJggg==);
|
||||||
|
*background-image:url(360-button-vis-play.png);
|
||||||
|
_background:transparent url(360-button-vis-play.gif) no-repeat 50% 50%;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360-vis:hover .sm2-360btn,
|
||||||
|
.ui360-vis .sm2-360btn-default:hover,
|
||||||
|
.ui360-vis .sm2-360ui.sm2_paused .sm2-360btn:hover {
|
||||||
|
background:transparent url(360-button-vis-play-light.png) no-repeat 50% 50%;
|
||||||
|
_background:transparent url(360-button-vis-play.gif) no-repeat 50% 50%;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ui360-vis .sm2-360ui.sm2_playing .sm2-360btn:hover,
|
||||||
|
.ui360-vis .sm2-360btn-playing:hover {
|
||||||
|
background:transparent url(360-button-vis-pause-light.png) no-repeat 50% 50%;
|
||||||
|
_background:transparent url(360-button-vis-pause-light.gif) no-repeat 50% 50%;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360-vis {
|
||||||
|
/* non-JS / before-loaded state */
|
||||||
|
background-position: 21% 50%;
|
||||||
|
_background:transparent url(360-button-vis-play.gif) no-repeat 21% 50%; /* IE 6-only: special crap GIF */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360-vis .sm2-360btn-default {
|
||||||
|
/* real button, post-loaded state */
|
||||||
|
_background:transparent url(360-button-vis-play.gif) no-repeat 50% 50%; /* IE 6-only: special crap GIF */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360-vis .sm2-360ui.sm2_dragging .sm2-360btn {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
|
@ -0,0 +1,271 @@
|
||||||
|
/* General warning: Beta-ish. Code could be a bit cleaner. */
|
||||||
|
|
||||||
|
.ui360, /* entire UI */
|
||||||
|
.sm2-360ui { /* canvas container */
|
||||||
|
position:relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360,
|
||||||
|
.sm2-360ui {
|
||||||
|
min-width:50px; /* should always be at least this. */
|
||||||
|
min-height:50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-360ui {
|
||||||
|
width:50px;
|
||||||
|
height:50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360,
|
||||||
|
.ui360 * {
|
||||||
|
vertical-align:middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-360ui {
|
||||||
|
position:relative;
|
||||||
|
display:inline-block; /* firefox 3 et al */
|
||||||
|
float:left; /* IE 6+7, firefox 2 needs this, inline-block would work with fx3 and others */
|
||||||
|
*display:inline;
|
||||||
|
/*
|
||||||
|
clear:left;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-360ui.sm2_playing,
|
||||||
|
.sm2-360ui.sm2_paused {
|
||||||
|
/* bump on top when active */
|
||||||
|
z-index:10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 a { /* .sm2_link class added to playable links by SM2 */
|
||||||
|
float:left;
|
||||||
|
display:inline;
|
||||||
|
position:relative;
|
||||||
|
color:#000;
|
||||||
|
text-decoration:none;
|
||||||
|
left:3px; /* slight spacing on left UI */
|
||||||
|
top:18px; /* vertical align */
|
||||||
|
text-indent:50px; /* make room for UI at left */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 a.sm2_link { /* SM2 has now started */
|
||||||
|
text-indent:0px; /* UI now in place. */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 a,
|
||||||
|
.ui360 a:hover,
|
||||||
|
.ui360 a:focus {
|
||||||
|
padding:2px;
|
||||||
|
margin-left:-2px;
|
||||||
|
margin-top:-2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 a:hover,
|
||||||
|
.ui360 a:focus {
|
||||||
|
background:#eee;
|
||||||
|
border-radius:3px;
|
||||||
|
outline:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-canvas {
|
||||||
|
position:absolute;
|
||||||
|
left:0px;
|
||||||
|
top:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-timing {
|
||||||
|
position:absolute;
|
||||||
|
display:block;
|
||||||
|
left:0px;
|
||||||
|
top:0px;
|
||||||
|
width:100%;
|
||||||
|
height:100%;
|
||||||
|
margin:0px;
|
||||||
|
font:11px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;
|
||||||
|
color:#666;
|
||||||
|
text-align:center;
|
||||||
|
line-height:50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-timing.alignTweak {
|
||||||
|
text-indent:1px; /* devious center-alignment tweak for Safari (might break things for others.) */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-cover {
|
||||||
|
position:absolute;
|
||||||
|
left:0px;
|
||||||
|
top:0px;
|
||||||
|
width:100%;
|
||||||
|
height:100%;
|
||||||
|
z-index:2;
|
||||||
|
display:none;
|
||||||
|
background-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==); /* old-skool bug: IE 9 won't catch mouse events otherwise. /smash */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360btn {
|
||||||
|
position:absolute;
|
||||||
|
display:block;
|
||||||
|
top:50%;
|
||||||
|
left:50%;
|
||||||
|
/*
|
||||||
|
width:22px;
|
||||||
|
height:22px;
|
||||||
|
margin-left:-11px;
|
||||||
|
margin-top:-11px;
|
||||||
|
*/
|
||||||
|
/* by default, cover whole space. make smaller when playing. */
|
||||||
|
width:50px;
|
||||||
|
height:50px;
|
||||||
|
margin-left:-25px;
|
||||||
|
margin-top:-25px;
|
||||||
|
border-radius: 25px;
|
||||||
|
cursor:pointer;
|
||||||
|
z-index:3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360data {
|
||||||
|
display:inline-block;
|
||||||
|
font-family:helvetica;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-block .ui360 .sm2-360btn,
|
||||||
|
.ui360 .sm2-360ui.sm2_playing .sm2-360btn,
|
||||||
|
.ui360 .sm2-360ui.sm2_paused .sm2-360btn {
|
||||||
|
/* smaller clickable button, in center */
|
||||||
|
width:22px;
|
||||||
|
height:22px;
|
||||||
|
margin-left:-11px;
|
||||||
|
margin-top:-11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360ui.sm2_playing .sm2-cover,
|
||||||
|
.ui360 .sm2-360ui.sm2_paused .sm2-cover {
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this could be optimized a fair bit. */
|
||||||
|
|
||||||
|
.ui360,
|
||||||
|
.ui360 .sm2-360btn-default,
|
||||||
|
.ui360 .sm2-360ui.sm2_paused .sm2-360btn {
|
||||||
|
background:transparent url(360-button-play.png) no-reoeat;
|
||||||
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAABoUlEQVR42sWVu2oCQRhGU/s8gpVYJeQJNkZSbiH4QNuLlQZS21sJayGYaOEFVFDxNiremj9zig2uzk5YQpKFg8PMd75ZZle9E5Ff4e+Ll8tlQuNoPI2vUcCYOdbIxCmm9F5T0YgNMmS/LebSwWdNa7VayXq9ls1mI9vtVna7nQBj5lgjQxYHN7KY3QkiUbDf7+V4PMrpdArBHGtkyOJc3/n1mVaUUl+F5/PZSrABDi4dpmKH3QkixQEHlw5TsccZmsRCoSD1et1ajkuHqdg/HA5GKZPJCOTzeanVasYMLh2mYsXDIGAoDuG6rlSr1WCdBxrcsTIWazgrQiHS6bSRYJ3XDzeq2O/3+9Ltdm9IpVIhstmslEqlUAY36ii8ZrMpjUbjhmQyKeA4jhSLRWMGN+rhOZ1Oh8ANuVxOyuUy40hwo163RK/XeyPQbrdjgYNr/ILAYDB41Gf1wZnFAQfX+iM0HA5fxuPx+2g0Ej22QoYsDq61mGsymTxMp9NX/Sk2yJDFsRZfXpzXbDZ7WiwW3nw+9zUKGDPHGpkL5V//mn7OJyJZApyzeUS5AAAAAElFTkSuQmCC);
|
||||||
|
*background-image: url(360-button-play.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 {
|
||||||
|
/*
|
||||||
|
"fake" button shown before SM2 has started, non-JS/non-SM2 case etc.
|
||||||
|
background image will be removed via JS, in threeSixyPlayer.init()
|
||||||
|
*/
|
||||||
|
background-position: 14px 50%;
|
||||||
|
_background:transparent url(360-button-play.gif) no-repeat 14px 50%; /* IE 6-only: special crap GIF */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360btn-default,
|
||||||
|
.ui360 .sm2-360ui.sm2_paused .sm2-360btn {
|
||||||
|
background-position:50% 50%;
|
||||||
|
_background:transparent url(360-button-play.gif) no-repeat 50% 50%; /* IE 6-only: special crap GIF */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360btn-default,
|
||||||
|
.ui360 .sm2-360ui.sm2_paused .sm2-360btn {
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360btn-default:hover,
|
||||||
|
.ui360 .sm2-360ui.sm2_paused .sm2-360btn:hover {
|
||||||
|
background:transparent url(360-button-play-light.png) no-repeat 50% 50%;
|
||||||
|
_background:transparent url(360-button-play.gif) no-repeat 50% 50%;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360ui.sm2_playing .sm2-360btn:hover,
|
||||||
|
.ui360 .sm2-360btn-playing:hover {
|
||||||
|
background:transparent url(360-button-pause-light.png) no-repeat 50% 50%;
|
||||||
|
_background:transparent url(360-button-pause-light.gif) no-repeat 50% 50%;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360ui.sm2_playing .sm2-timing {
|
||||||
|
visibility:visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360ui.sm2_buffering .sm2-timing {
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360ui .sm2-timing,
|
||||||
|
.ui360 .sm2-360ui .sm2-360btn:hover + .sm2-timing,
|
||||||
|
.ui360 .sm2-360ui.sm2_paused .sm2-timing {
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360ui.sm2_dragging .sm2-timing,
|
||||||
|
.ui360 .sm2-360ui.sm2_dragging .sm2-360btn:hover + .sm2-timing {
|
||||||
|
/* paused + dragging */
|
||||||
|
visibility:visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360ui.sm2_playing .sm2-360btn,
|
||||||
|
.ui360 .sm2-360ui.sm2_dragging .sm2-360btn,
|
||||||
|
.ui360 .sm2-360ui.sm2_dragging .sm2-360btn:hover,
|
||||||
|
.ui360 .sm2-360ui.sm2_dragging .sm2-360btn-playing:hover {
|
||||||
|
/* don't let pause button show on hover when dragging (or paused and dragging) */
|
||||||
|
background:transparent;
|
||||||
|
cursor:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 .sm2-360ui.sm2_buffering .sm2-360btn,
|
||||||
|
.ui360 .sm2-360ui.sm2_buffering .sm2-360btn:hover {
|
||||||
|
background:transparent url(icon_loading_spinner.gif) no-repeat 50% 50%;
|
||||||
|
opacity:0.5;
|
||||||
|
visibility:visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* inline list style */
|
||||||
|
|
||||||
|
.sm2-inline-list .ui360,
|
||||||
|
.sm2-inline-block .ui360 {
|
||||||
|
position:relative;
|
||||||
|
display:inline-block;
|
||||||
|
float:left;
|
||||||
|
_display:inline;
|
||||||
|
margin-bottom:-15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-list .ui360 {
|
||||||
|
/* inline player: minor tweak, tighten spacing */
|
||||||
|
margin-right:-2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-block .ui360 {
|
||||||
|
margin-right:8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm2-inline-list .ui360 a {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* annotations */
|
||||||
|
|
||||||
|
ul.ui360playlist {
|
||||||
|
list-style-type:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.ui360playlist,
|
||||||
|
ul.ui360playlist li {
|
||||||
|
margin:0px;
|
||||||
|
padding:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.ui360 div.metadata {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.ui360 a span.metadata,
|
||||||
|
div.ui360 a span.metadata * {
|
||||||
|
/* name of track, note etc. */
|
||||||
|
vertical-align:baseline;
|
||||||
|
}
|
|
@ -0,0 +1,132 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||||
|
<head>
|
||||||
|
<title>360° MP3 player UI demo (SoundManager 2): Javascript + Canvas Visualization, basic example</title>
|
||||||
|
<meta name="robots" content="noindex" />
|
||||||
|
<meta name="description" content="Basic example of 360-degree circular control for MP3 links, with EQ and spectrum visualization options" />
|
||||||
|
<!-- demo: make the fonts nicer etc. -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="../index.css" />
|
||||||
|
|
||||||
|
<!-- soundManager.useFlashBlock: related CSS -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />
|
||||||
|
|
||||||
|
<!-- required -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="360player.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="360player-visualization.css" />
|
||||||
|
|
||||||
|
<!-- special IE-only canvas fix -->
|
||||||
|
<!--[if IE]><script type="text/javascript" src="script/excanvas.js"></script><![endif]-->
|
||||||
|
|
||||||
|
<!-- Apache-licensed animation library -->
|
||||||
|
<script type="text/javascript" src="script/berniecode-animator.js"></script>
|
||||||
|
|
||||||
|
<!-- the core stuff -->
|
||||||
|
<script type="text/javascript" src="../../script/soundmanager2.js"></script>
|
||||||
|
<script type="text/javascript" src="script/360player.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
soundManager.setup({
|
||||||
|
// path to directory containing SM2 SWF
|
||||||
|
url: '../../swf/'
|
||||||
|
});
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.scaleFont = (navigator.userAgent.match(/msie/i)?false:true);
|
||||||
|
threeSixtyPlayer.config.showHMSTime = true;
|
||||||
|
|
||||||
|
// enable some spectrum stuffs
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.useWaveformData = true;
|
||||||
|
threeSixtyPlayer.config.useEQData = true;
|
||||||
|
|
||||||
|
// enable this in SM2 as well, as needed
|
||||||
|
|
||||||
|
if (threeSixtyPlayer.config.useWaveformData) {
|
||||||
|
soundManager.flash9Options.useWaveformData = true;
|
||||||
|
}
|
||||||
|
if (threeSixtyPlayer.config.useEQData) {
|
||||||
|
soundManager.flash9Options.useEQData = true;
|
||||||
|
}
|
||||||
|
if (threeSixtyPlayer.config.usePeakData) {
|
||||||
|
soundManager.flash9Options.usePeakData = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (threeSixtyPlayer.config.useWaveformData || threeSixtyPlayer.flash9Options.useEQData || threeSixtyPlayer.flash9Options.usePeakData) {
|
||||||
|
// even if HTML5 supports MP3, prefer flash so the visualization features can be used.
|
||||||
|
soundManager.preferFlash = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// favicon is expensive CPU-wise, but can be enabled.
|
||||||
|
threeSixtyPlayer.config.useFavIcon = false;
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="demo.css" />
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
#left h2 {
|
||||||
|
padding-top:0px;
|
||||||
|
margin-bottom:0.25em;
|
||||||
|
color:#666;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.block {
|
||||||
|
margin-top:0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* special case */
|
||||||
|
|
||||||
|
#left {
|
||||||
|
width:auto;
|
||||||
|
max-width:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="left">
|
||||||
|
|
||||||
|
<h1><a href="http://schillmania.com/projects/soundmanager2/demo/360-player/">360° Player Demo</a> - Visualization Example, Basic Template</h1>
|
||||||
|
|
||||||
|
<p class="note" style="color:#666;margin-bottom:0.5em">Canvas-based UI with visualization options. <b>Note: No EQ/spectrum support for IE < 9 (too slow.) Data not implemented in HTML5.</b></p>
|
||||||
|
|
||||||
|
<div style="clear:left"></div>
|
||||||
|
|
||||||
|
<div id="sm2-container">
|
||||||
|
<!-- sm2 flash goes here -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- here are the MP3 links, which are decorated with the 360 canvas element/UI etc. -->
|
||||||
|
|
||||||
|
<h2 style="margin-top:1em">Inline list</h2>
|
||||||
|
|
||||||
|
<div class="sm2-inline-list"> <!-- remove this class to have one item per line -->
|
||||||
|
|
||||||
|
<div class="ui360 ui360-vis"><a href="../../demo/mpc/audio/CRASH_1.mp3">Crash 1</a></div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="../../demo/mpc/audio/CRASH_5.mp3">Crash 5</a></div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="../../demo/mpc/audio/CRASH_6.mp3">Crash 6</a></div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="../../demo/mpc/audio/CHINA_1.mp3">China 1</a></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 style="clear:both;padding-top:1em">Block list</h2>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="../../demo/_mp3/sine,%20square,%20sawtooth,%20rando.mp3">Sine, Square, Sawtooth, Wave (Warning: LOUD)</a></div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="../../demo/_mp3/1hz-10khz-sweep.mp3">1-10 Khz Sweep (Warning: LOUD)</a></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p style="margin-left:1em">
|
||||||
|
<a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 home">SoundManager 2 project page</a> (not an MP3 link)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,359 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||||
|
<head>
|
||||||
|
<title>360° MP3 player UI demo (SoundManager 2): Javascript + Canvas Visualization</title>
|
||||||
|
<meta name="robots" content="noindex" />
|
||||||
|
<meta name="description" content="Javascript + Canvas + SoundManager 2: 360-degree circular control / jog wheel example for playing MP3 links, with EQ and spectrum visualization options" />
|
||||||
|
<!-- demo, make the fonts nicer etc. -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="../index.css" />
|
||||||
|
|
||||||
|
<!-- soundManager.useFlashBlock: related CSS -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />
|
||||||
|
|
||||||
|
<!-- required -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="360player.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="360player-visualization.css" />
|
||||||
|
|
||||||
|
<!-- special IE-only canvas fix -->
|
||||||
|
<!--[if IE]><script type="text/javascript" src="script/excanvas.js"></script><![endif]-->
|
||||||
|
|
||||||
|
<!-- Apache-licensed animation library -->
|
||||||
|
<script type="text/javascript" src="script/berniecode-animator.js"></script>
|
||||||
|
|
||||||
|
<!-- the core stuff -->
|
||||||
|
<script type="text/javascript" src="../../script/soundmanager2.js"></script>
|
||||||
|
<script type="text/javascript" src="script/360player.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
soundManager.setup({
|
||||||
|
// path to directory containing SM2 SWF
|
||||||
|
url: '../../swf/'
|
||||||
|
});
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.scaleFont = (navigator.userAgent.match(/msie/i)?false:true);
|
||||||
|
threeSixtyPlayer.config.showHMSTime = true;
|
||||||
|
|
||||||
|
// enable some spectrum stuffs
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.useWaveformData = true;
|
||||||
|
threeSixtyPlayer.config.useEQData = true;
|
||||||
|
|
||||||
|
// enable this in SM2 as well, as needed
|
||||||
|
|
||||||
|
if (threeSixtyPlayer.config.useWaveformData) {
|
||||||
|
soundManager.flash9Options.useWaveformData = true;
|
||||||
|
}
|
||||||
|
if (threeSixtyPlayer.config.useEQData) {
|
||||||
|
soundManager.flash9Options.useEQData = true;
|
||||||
|
}
|
||||||
|
if (threeSixtyPlayer.config.usePeakData) {
|
||||||
|
soundManager.flash9Options.usePeakData = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (threeSixtyPlayer.config.useWaveformData || threeSixtyPlayer.flash9Options.useEQData || threeSixtyPlayer.flash9Options.usePeakData) {
|
||||||
|
// even if HTML5 supports MP3, prefer flash so the visualization features can be used.
|
||||||
|
soundManager.preferFlash = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// favicon is expensive CPU-wise, but can be used.
|
||||||
|
if (window.location.href.match(/hifi/i)) {
|
||||||
|
threeSixtyPlayer.config.useFavIcon = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.location.href.match(/html5/i)) {
|
||||||
|
// for testing IE 9, etc.
|
||||||
|
soundManager.useHTML5Audio = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- DEMO only, customization UI: Yahoo! YUI colorpicker stuff -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.7.0/build/slider/assets/skins/sam/slider.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.7.0/build/colorpicker/assets/skins/sam/colorpicker.css" />
|
||||||
|
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>
|
||||||
|
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/animation/animation-min.js"></script>
|
||||||
|
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/dragdrop/dragdrop-min.js"></script>
|
||||||
|
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/slider/slider-min.js"></script>
|
||||||
|
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/element/element-min.js"></script>
|
||||||
|
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/colorpicker/colorpicker-min.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="demo.css" />
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left h2 {
|
||||||
|
padding-top:0px;
|
||||||
|
margin-bottom:0.25em;
|
||||||
|
color:#666;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.block {
|
||||||
|
margin-top:0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* special case */
|
||||||
|
|
||||||
|
#left {
|
||||||
|
width:auto;
|
||||||
|
max-width:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui360 span {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- demo configuration stuff, you don't need this -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="demo-slider-controls.css" />
|
||||||
|
<script type="text/javascript" src="demo-slider-controls.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="left">
|
||||||
|
|
||||||
|
<h1><a href="http://www.schillmania.com/projects/soundmanager2/" title="Javascript MP3 player project home">SoundManager 2</a> / <a href="http://schillmania.com/projects/soundmanager2/demo/360-player/">360° Player Demo</a>: JS + Canvas Visualization</h1>
|
||||||
|
|
||||||
|
<p class="note" style="color:#666;margin-top:0.5em;margin-bottom:0.5em">Canvas-based UI with visualization options. <b>Note: Spectrum/EQ visualizations disabled for IE < 9 (too slow.) Data is not implemented under HTML5.</b></p>
|
||||||
|
<p class="note" style="color:#666;margin-bottom:0.5em">You can also <a href="#debug=1" onclick="window.location.href = this.href;window.location.reload()" title="Enable debug mode, show frames per second">show FPS</a><span id="config-link"> or <a href="#customize" onclick="window.location.href=this.href;window.location.reload()">customize the UI</a></span><span id="hifi">, or see the <a href="#hifi=1" onclick="window.location.href=this.href;window.location.reload()">hi-fi version</a></span>. Check the <a href="canvas-visualization-basic.html">basic template</a> for a minimal code example; also see the <a href="../360-player/" title="360° player UI">default 360° UI</a>.</p>
|
||||||
|
|
||||||
|
<!-- customization crap -->
|
||||||
|
|
||||||
|
<div id="config-ui" style="clear:both;position:relative;max-width:1110px;margin-top:1em;display:none">
|
||||||
|
|
||||||
|
<div style="position:relative">
|
||||||
|
|
||||||
|
<form action="#" method="get">
|
||||||
|
|
||||||
|
<div id="controls">
|
||||||
|
|
||||||
|
<div class="checkbox">
|
||||||
|
<div>
|
||||||
|
<input id="use-waveform" type="checkbox" checked="checked" title="Enable waveform feature." onclick="controller.updateExample();controller.updateExampleCode()" value="Apply" /> Waveform
|
||||||
|
<input id="disabled-1" type="checkbox" title="Enable EQ (spectrum) feature." onclick="controller.updateExample();controller.updateExampleCode()" value="Apply" style="margin-left:1em" checked="checked" /> EQ
|
||||||
|
<input type="checkbox" name="use-amplifier" id="use-amplifier" checked="checked" onclick="controller.updateExample();controller.updateExampleCode()" style="margin-left:1em"> Amplifier
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="clear:left"></div>
|
||||||
|
|
||||||
|
<dl class="col">
|
||||||
|
|
||||||
|
<dt>Circle Diameter</dt>
|
||||||
|
<dd class="title">Size</dd>
|
||||||
|
<dd>1-256</dd>
|
||||||
|
<dd class="control">
|
||||||
|
<div class="bar" title="Click to move here"></div>
|
||||||
|
<div class="slider" title="Size of circle"></div>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>Waveform Thickness</dt>
|
||||||
|
<dd class="title">thickness</dd>
|
||||||
|
<dd>1-100</dd>
|
||||||
|
<dd class="control">
|
||||||
|
<div class="bar" title="Click to move here"></div>
|
||||||
|
<div class="slider" title="Thickness of line"></div>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>Wave Downsample</dt>
|
||||||
|
<dd class="title">(Scale)</dd>
|
||||||
|
<dd>1-16</dd>
|
||||||
|
<dd class="control">
|
||||||
|
<div class="bar" title="Click to move here"></div>
|
||||||
|
<div class="slider" title="Amount to downsample waveform data by"></div>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>EQ Thickness</dt>
|
||||||
|
<dd class="title">thickness</dd>
|
||||||
|
<dd>1-50</dd>
|
||||||
|
<dd class="control">
|
||||||
|
<div class="bar" title="Click to move here"></div>
|
||||||
|
<div class="slider" title="Thickness of line"></div>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>EQ Downsample</dt>
|
||||||
|
<dd class="title">(Scale)</dd>
|
||||||
|
<dd>1-16</dd>
|
||||||
|
<dd class="control">
|
||||||
|
<div class="bar" title="Click to move here"></div>
|
||||||
|
<div class="slider" title="Amount to downsample EQ data by"></div>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>Ring Thickness</dt>
|
||||||
|
<dd class="title">(Scale)</dd>
|
||||||
|
<dd>1-200</dd>
|
||||||
|
<dd class="control">
|
||||||
|
<div class="bar" title="Click to move here"></div>
|
||||||
|
<div class="slider" title="Scale factor for the ring width"></div>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<div id="options" class="col">
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Waveform position:
|
||||||
|
<input type="radio" name="waveform-inside" id="waveform-inside" value="true" checked="checked" onclick="controller.updateExample();controller.updateExampleCode()"> Inside | <input type="radio" name="waveform-inside" id="waveform-inside" value="false" onclick="controller.updateExample();controller.updateExampleCode()"> Outside
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
EQ position:
|
||||||
|
<input type="radio" name="eq-inside" id="eq-inside" value="true" onclick="controller.updateExample();controller.updateExampleCode()"> Inside | <input type="radio" name="eq-inside" id="eq-inside" value="false" checked="checked" onclick="controller.updateExample();controller.updateExampleCode()"> Outside
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Waveform color:
|
||||||
|
<input type="text" name="waveform-color" id="waveform-color" value="#000000" onclick="createCP(this,setWaveformColor)" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
EQ color:
|
||||||
|
<input type="text" name="eq-color" id="eq-color" value="#000000" onclick="createCP(this,setEQColor)" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Loaded ring color:
|
||||||
|
<input type="text" name="loaded-ring-color" id="loaded-ring-color" value="#000000" onclick="createCP(this,setLoadedRingColor)" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Progress ring color:
|
||||||
|
<input type="text" name="progress-ring-color" id="progress-ring-color" value="#000000" onclick="createCP(this,setProgressRingColor)" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Background ring color:
|
||||||
|
<input type="text" name="bg-ring-color" id="bg-ring-color" value="#000000" onclick="createCP(this,setBackgroundRingColor)" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="compact">
|
||||||
|
<input type="button" onclick="controller.randomize()" value="Randomize controls" title="Assign random control values" style="font-size:x-small" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="cp-container">
|
||||||
|
<!-- color picker stuff goes here -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="config-code-block" style="float:right;display:inline;margin-left:1em;margin-top:-0.7em">
|
||||||
|
<!--
|
||||||
|
<pre id="config-link" class="block"><code style="cursor:pointer" onclick="document.getElementById('config-link').style.display='none';document.getElementById('config-pre-block').style.display='block';return false"> [click to show code] </code></pre>
|
||||||
|
-->
|
||||||
|
<pre id="config-pre-block" class="block"><code id="config-code">Code goes here</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p style="clear:left">Get a sound playing, then adjust the values to see real-time updates.</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- here are the MP3 links, which are decorated with the 360 canvas element/UI etc. -->
|
||||||
|
|
||||||
|
<div id="sm2-container">
|
||||||
|
<!-- sm2 flash goes here -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 style="margin-top:1em">Inline list</h2>
|
||||||
|
|
||||||
|
<div class="sm2-inline-list"> <!-- remove this class to have one item per line -->
|
||||||
|
|
||||||
|
<div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/The%20Fugitives%20-%20Graffiti%20Sex.mp3">The Fugitives - Graffiti Sex</a></div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/Adrian%20Glynn%20-%20Blue%20Belle%20Lament.mp3">Adrian Glynn - Blue Belle Lament</a></div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20I%20Tried.mp3">SonReal - I Tried</a></div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20People%20Asking.mp3">SonReal - People Asking</a></div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/mpc/20060826%20-%20Armstrong.mp3">20060826 - Armstrong Groove</a></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="note medium-note" style="clear:both"><b>Artist thank-yous</b>: "Graffiti Sex" courtesy of <a href="http://www.fugitives.ca/" title="A group of musicians, poets, and multi-instrumentalists from Vancouver, Canada">The Fugitives</a>. "Blue Belle Lament" courtesy of <a href="http://www.adrianglynn.com/" title="Adrian Glynn, Vancouver-based Singer/Songwriter">Adrian Glynn</a>. "I Tried" and "People Asking" courtesy of <a href="http://sonreal.bandcamp.com/album/the-lightyear-mixtape" title="The Lightyear Mixtape from SonReal, Vancouver-based hip-hop artist">SonReal</a>.</p>
|
||||||
|
|
||||||
|
<h2 style="clear:left;padding-top:1em">Block list</h2>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/mpc/20090207%20-%20Loverman.mp3">20090207 - Loverman</a></div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/dialup.mp3">56K Modem dial-up sound (Warning: <span style="color:#ff3333">LOUD</span>)</a></div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="../../demo/_mp3/1hz-10khz-sweep.mp3">1-10 Khz Sweep (Warning: <span style="color:#ff3333">LOUD</span>)</a></div>
|
||||||
|
<div class="ui360 ui360-vis"><a href="../../demo/_mp3/sine,%20square,%20sawtooth,%20rando.mp3">Sine, Square, Sawtooth, Wave (Warning: <span style="color:#ff3333">LOUD</span>)</a></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="note medium-note" style="clear:left">56K Modem sound (Creative Commons license) via <a href="http://www.freesound.org/samplesViewSingle.php?id=16475">dialup.mp3</a>, from freesound.org user <a href="http://www.freesound.org/usersViewSingle.php?id=54447">Jlew</a>.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2 style="clear:left;padding-top:1em">Variant: Annotations/meta-data</h2>
|
||||||
|
|
||||||
|
|
||||||
|
<ul class="ui360playlist">
|
||||||
|
|
||||||
|
<li>
|
||||||
|
|
||||||
|
<div class="ui360 ui360-vis">
|
||||||
|
<a href="http://freshly-ground.com/data/audio/binaural/A%20Virtual%20Haircut%20in%20San%20Francisco%20%283%20Scenes%29.mp3">A Virtual Haircut (3 scenes)</a>
|
||||||
|
<div class="metadata">
|
||||||
|
<div class="duration">4:43</div> <!-- total track time (for positioning while loading, until determined -->
|
||||||
|
<ul>
|
||||||
|
<li><p>Electric razor</p><span>0:00</span></li> <!-- first scene -->
|
||||||
|
<li><p>Water, scissors</p><span>2:41</span></li> <!-- start time of second scene -->
|
||||||
|
<li><p>More razor work</p><span>4:00</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
|
||||||
|
<div class="ui360 ui360-vis">
|
||||||
|
<a href="http://freshly-ground.com/data/audio/binaural/Rubber%20Chicken%20Launch%20%28office%29.mp3">Rubber Chicken Launch (Office)</a>
|
||||||
|
|
||||||
|
<div class="metadata">
|
||||||
|
<div class="duration">0:47</div>
|
||||||
|
<ul>
|
||||||
|
<li><p>First attempt</p><span>0:00</span></li>
|
||||||
|
<li><p>Fire!</p><span>0:02</span></li>
|
||||||
|
<li><p>"Too much angle"</p><span>0:05</span></li>
|
||||||
|
<li><p>Random chicken noise</p><span>0:18</span></li>
|
||||||
|
<li><p>"Wait a second"</p><span>0:31</span></li>
|
||||||
|
<li><p>Derrr..</p><span>0:34</span></li>
|
||||||
|
<li><p>Launch attempt #2</p><span>0:36</span></li>
|
||||||
|
<li><p>"Wrong angle"</p><span>0:39</span></li>
|
||||||
|
<li><p>"Fail"</p><span>0:42</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div style="clear:both"></div>
|
||||||
|
|
||||||
|
<p style="margin-left:1em">
|
||||||
|
<a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 home">SoundManager 2 project page</a> (not an MP3 link)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
if (window.location.toString().match(/#customize/i)) {
|
||||||
|
document.getElementById('config-link').style.display = 'none';
|
||||||
|
document.getElementById('config-ui').style.display = 'block';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,179 @@
|
||||||
|
#cp-container { position:relative;float:left;display:inline; margin-left:1em;padding: 6px; background-color: #f6f6f6; border:1px solid #eee; width: 320px; height:180px;z-index:2; }
|
||||||
|
|
||||||
|
.yui-picker-controls li,
|
||||||
|
.yui-picker-controls input {
|
||||||
|
font-size:1em;
|
||||||
|
font-family:"helvetica neue",helvetica,arial,verdana;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls {
|
||||||
|
position:relative;
|
||||||
|
margin-top:1.5em;
|
||||||
|
font-size:0.85em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#options {
|
||||||
|
float:left;
|
||||||
|
display:inline;
|
||||||
|
margin-bottom:0.5em;
|
||||||
|
margin-top:-1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .checkbox {
|
||||||
|
float:left;
|
||||||
|
display:inline;
|
||||||
|
width:21.2em;
|
||||||
|
margin-right:2.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .checkbox div {
|
||||||
|
/* tab */
|
||||||
|
width:auto;
|
||||||
|
padding:0.4em;
|
||||||
|
border:1px solid #ddd;
|
||||||
|
border-bottom:none;
|
||||||
|
background:#eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .checkbox div,
|
||||||
|
#controls .checkbox input {
|
||||||
|
font-family:arial,tahoma,verdana,"sans serif";
|
||||||
|
font-size:1em;
|
||||||
|
vertical-align:middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls dl {
|
||||||
|
width:21em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls dl.col {
|
||||||
|
position:relative;
|
||||||
|
float:left;
|
||||||
|
display:inline;
|
||||||
|
margin:0px;
|
||||||
|
margin-right:1em;
|
||||||
|
padding:0.75em;
|
||||||
|
/*
|
||||||
|
height:12.4em;
|
||||||
|
*/
|
||||||
|
height:auto;
|
||||||
|
border:1px solid #ddd;
|
||||||
|
background:#f6f6f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .disabled {
|
||||||
|
color:#ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .disabled dt,
|
||||||
|
#controls .disabled dd {
|
||||||
|
color:#999;
|
||||||
|
opacity:0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls dl dd p {
|
||||||
|
margin:0px;
|
||||||
|
padding:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls dt,
|
||||||
|
#controls dd {
|
||||||
|
margin:0px;
|
||||||
|
padding:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls dt {
|
||||||
|
border-bottom:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls dt {
|
||||||
|
float:left;
|
||||||
|
display:inline;
|
||||||
|
background:transparent;
|
||||||
|
padding-right:0.7em;
|
||||||
|
margin-right:0.7em;
|
||||||
|
border-right:1px solid #ccc;
|
||||||
|
font-size:1.1em;
|
||||||
|
color:#333;
|
||||||
|
font-family:"helvetica neue",helvetica,verdana,arial,"sans serif";
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls dd {
|
||||||
|
margin:0px;
|
||||||
|
padding:0px;
|
||||||
|
font-size:0.9em;
|
||||||
|
vertical-align:middle;
|
||||||
|
color:#666;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .title {
|
||||||
|
float:left;
|
||||||
|
display:inline;
|
||||||
|
margin-right:0.6em;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* those slider bits you might be wondering about */
|
||||||
|
|
||||||
|
#controls .control {
|
||||||
|
position:relative;
|
||||||
|
border-left:0px;
|
||||||
|
width:214px;
|
||||||
|
height:20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .control .bar {
|
||||||
|
position:absolute;
|
||||||
|
left:0px;
|
||||||
|
top:0px;
|
||||||
|
width:214px;
|
||||||
|
height:20px;
|
||||||
|
background:transparent url(../_image/slider-bar.gif) no-repeat 0px 9px;
|
||||||
|
cursor:pointer;
|
||||||
|
cursor:hand;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .control .slider {
|
||||||
|
position:absolute;
|
||||||
|
left:0px;
|
||||||
|
top:0px;
|
||||||
|
width:20px;
|
||||||
|
height:20px;
|
||||||
|
background:transparent url(../_image/slider.png) no-repeat 0px 0px;
|
||||||
|
*background:none;
|
||||||
|
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider.png');
|
||||||
|
cursor:pointer;
|
||||||
|
cursor:hand;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .control .slider:hover {
|
||||||
|
background:transparent url(../_image/slider-1.png) no-repeat 0px 0px;
|
||||||
|
*background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .control .slider.hover {
|
||||||
|
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider-1.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .disabled .control .slider {
|
||||||
|
background:transparent url(../_image/slider-disabled.png) no-repeat 0px 0px;
|
||||||
|
*background:none;
|
||||||
|
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider-disabled.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .disabled .control .slider:hover {
|
||||||
|
background:transparent url(../_image/slider-disabled-1.png) no-repeat 0px 0px;
|
||||||
|
*background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls .disabled .control .slider.hover {
|
||||||
|
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider-disabled-1.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls input[type=text] {
|
||||||
|
width:5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#options div {
|
||||||
|
margin-bottom:0.25em;
|
||||||
|
}
|
|
@ -0,0 +1,750 @@
|
||||||
|
/*
|
||||||
|
Ancient fireworks slider control code (2005)
|
||||||
|
Kinda/sorta refactored for SM2 360 demo
|
||||||
|
http://schillmania.com/projects/fireworks/
|
||||||
|
--------------------------------------------
|
||||||
|
Not required for your use!
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Animator2() {
|
||||||
|
var self = this;
|
||||||
|
this.tweens = [];
|
||||||
|
this.tweens['default'] = [1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1];
|
||||||
|
this.tweens['blast'] = [12,12,11,10,10,9,8,7,6,5,4,3,2,1];
|
||||||
|
this.tweens['fade'] = [10,10,10,10,10,10,10,10,10,10];
|
||||||
|
this.queue = [];
|
||||||
|
this.queue.IDs = [];
|
||||||
|
this.active = false;
|
||||||
|
this.timer = null;
|
||||||
|
|
||||||
|
this.createTween = function(start,end,type) {
|
||||||
|
// return array of tween coordinate data (start->end)
|
||||||
|
type = type||'default';
|
||||||
|
var tween = [start];
|
||||||
|
var tmp = start;
|
||||||
|
var diff = end-start;
|
||||||
|
var x = self.tweens[type].length;
|
||||||
|
for (var i=0; i<x; i++) {
|
||||||
|
tmp += diff*self.tweens[type][i]*0.01;
|
||||||
|
tween[i] = new Object();
|
||||||
|
tween[i].data = tmp;
|
||||||
|
tween[i].event = null;
|
||||||
|
}
|
||||||
|
return tween;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.enqueue = function(o,fMethod,fOnComplete) {
|
||||||
|
// add object and associated methods to animation queue
|
||||||
|
// writeDebug('animator.enqueue()');
|
||||||
|
if (!fMethod) {
|
||||||
|
// writeDebug('animator.enqueue(): missing fMethod');
|
||||||
|
}
|
||||||
|
if (typeof(self.queue.IDs[o.oID])=='undefined') {
|
||||||
|
// writeDebug('animator.enqueue(): added '+o.oID);
|
||||||
|
var i = self.queue.length;
|
||||||
|
self.queue.IDs[o.oID] = i;
|
||||||
|
self.queue[i] = o;
|
||||||
|
} else {
|
||||||
|
// writeDebug('animator.enqueue(): '+o.oID+' already queued');
|
||||||
|
var i = self.queue.IDs[o.oID]; // retrieve queue index
|
||||||
|
self.queue[i].active = true;
|
||||||
|
self.queue[i].frame = 0;
|
||||||
|
}
|
||||||
|
o.active = true; // flag for animation
|
||||||
|
self.queue[i]._method = fMethod;
|
||||||
|
self.queue[i]._oncomplete = fOnComplete?fOnComplete:null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.animate = function() {
|
||||||
|
var active = 0;
|
||||||
|
for (var i=self.queue.length; i--;) {
|
||||||
|
if (self.queue[i].active) {
|
||||||
|
self.queue[i]._method();
|
||||||
|
active++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (active==0 && self.timer) {
|
||||||
|
// all animations finished
|
||||||
|
self.stop();
|
||||||
|
} else {
|
||||||
|
// writeDebug(active+' active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.start = function() {
|
||||||
|
if (self.timer || self.active) {
|
||||||
|
// writeDebug('animator.start(): already active');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// writeDebug('animator.start()'); // report only if started
|
||||||
|
self.active = true;
|
||||||
|
self.timer = setInterval(self.animate,mc.intervalRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.stop = function() {
|
||||||
|
// writeDebug('animator.stop()',true);
|
||||||
|
clearInterval(self.timer);
|
||||||
|
self.timer = null;
|
||||||
|
self.active = false;
|
||||||
|
self.queue = [];
|
||||||
|
self.queue.IDs = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function MainController() {
|
||||||
|
var self = this;
|
||||||
|
this.intervalRate = 20; // rate (ms) to run animation at, general best default = 20
|
||||||
|
this.DEBUG = true; // debug mode disabled by default
|
||||||
|
this.oFW = null;
|
||||||
|
this.isIE = (navigator.appVersion.indexOf('MSIE')+1);
|
||||||
|
this.isOpera = (navigator.userAgent.toLowerCase().indexOf('opera')+1);
|
||||||
|
if (this.isOpera) this.isIE = false; // no impersonation allowed here!
|
||||||
|
this.animator = null;
|
||||||
|
this.gOID = 0; // global object ID counter (for animation queue)
|
||||||
|
this.particleTypes = 6;
|
||||||
|
this.particleXY = 10;
|
||||||
|
this.tweenFade = [100,90,80,70,60,50,40,30,20,10,0];
|
||||||
|
this.isSafari = (navigator.appVersion.toLowerCase().indexOf('safari')+1?1:0);
|
||||||
|
this.canvasX = null;
|
||||||
|
this.canvasY = null;
|
||||||
|
this.screenY = null; // screen area (not entire page)
|
||||||
|
self.scrollY = null;
|
||||||
|
|
||||||
|
self.getWindowCoords = function() {
|
||||||
|
self.canvasX = (document.documentElement.clientWidth||document.body.clientWidth||document.body.scrollWidth);
|
||||||
|
self.canvasY = (document.documentElement.clientHeight||document.body.clientHeight||document.body.scrollHeight);
|
||||||
|
self.screenY = self.canvasY;
|
||||||
|
self.scrollY = parseInt(window.scrollY||document.documentElement.scrollTop||document.body.scrollTop);
|
||||||
|
self.canvasY += self.scrollY;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getWindowCoordsAlt = function() {
|
||||||
|
self.canvasX = window.innerWidth;
|
||||||
|
self.canvasY = window.innerHeight;
|
||||||
|
self.screenY = self.canvasY;
|
||||||
|
self.scrollY = parseInt(window.scrollY||document.documentElement.scrollTop||document.body.scrollTop);
|
||||||
|
self.canvasY += self.scrollY;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getPanX = function(x) {
|
||||||
|
x = parseInt(x);
|
||||||
|
var pos = x/self.canvasX;
|
||||||
|
if (pos<0.4) {
|
||||||
|
pos *= -1;
|
||||||
|
} else if (pos >= 0.4 && pos <= 0.6) {
|
||||||
|
pos = 0.5;
|
||||||
|
}
|
||||||
|
pos = parseInt(pos*100);
|
||||||
|
// writeDebug('getPanX('+x+'): '+pos+'%');
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isEmpty = function(o) {
|
||||||
|
// needs further hacking
|
||||||
|
return (typeof(o)=='undefined'||(o==null&&o!=0)||(o==''&&o!=0)||o=='null');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.init = function() {
|
||||||
|
// self.oFW = document.getElementById('fw');
|
||||||
|
// self.oFP = document.getElementById('fp');
|
||||||
|
// if (typeof(enableDebugMode)!='undefined' && (self.DEBUG||window.location.toString().toLowerCase().indexOf('debug')>=0)) enableDebugMode();
|
||||||
|
self.getWindowCoords();
|
||||||
|
self.animator = new Animator2();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.destructor = function() {
|
||||||
|
/*
|
||||||
|
for (var i=self.fireworks.length; i--;) {
|
||||||
|
self.fireworks[i] = null;
|
||||||
|
}
|
||||||
|
self.fireworks = null;
|
||||||
|
if (soundManager) {
|
||||||
|
soundManager.destructor();
|
||||||
|
soundManager = null;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isSafari || this.isOpera) this.getWindowCoords = this.getWindowCoordsAlt;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function Controller(o) {
|
||||||
|
var self = this;
|
||||||
|
this.o = o;
|
||||||
|
this.controls = [];
|
||||||
|
this.cb = [];
|
||||||
|
this.options = [];
|
||||||
|
this.functionExample = document.getElementById('function-example');
|
||||||
|
this.fbIE = null;
|
||||||
|
|
||||||
|
this.randomize = function() {
|
||||||
|
for (var i=1; i<self.controls.length; i++) {
|
||||||
|
setTimeout(self.controls[i].randomize,20+(20*i+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cbClick = function(nIndex) {
|
||||||
|
document.getElementById('controls').getElementsByTagName('dl')[nIndex].className = 'col'+(this.checked==false||this.checked==''?' disabled':'');
|
||||||
|
self.updateExample();
|
||||||
|
self.updateExampleCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateExample = function() {
|
||||||
|
if (threeSixtyPlayer) {
|
||||||
|
var val = self.controls[0].value;
|
||||||
|
threeSixtyPlayer.config.circleDiameter = self.controls[0].value;
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.circleRadius = self.controls[0].value/2;
|
||||||
|
// update some stuff
|
||||||
|
|
||||||
|
// set the cover width/height to match the canvas
|
||||||
|
if (threeSixtyPlayer.lastSound) {
|
||||||
|
// always set cover to max area?
|
||||||
|
// threeSixtyPlayer.lastSound._data.oCover.style.width = 250+'px';
|
||||||
|
// threeSixtyPlayer.lastSound._data.oCover.style.height = 250+'px';
|
||||||
|
// threeSixtyPlayer.lastSound._data.oCover.style.width = threeSixtyPlayer.config.circleDiameter+'px';
|
||||||
|
// threeSixtyPlayer.lastSound._data.oCover.style.height = threeSixtyPlayer.config.circleDiameter+'px';
|
||||||
|
threeSixtyPlayer.refreshCoords(threeSixtyPlayer.lastSound);
|
||||||
|
}
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.waveformDataLineRatio = (self.controls[1].value/100)*2;
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.waveformDataDownsample = (self.controls[2].value);
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.eqDataLineRatio = parseInt((self.controls[3].value/100)*3*1000)/1000;
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.eqDataDownsample = (self.controls[4].value);
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.scaleArcWidth = (self.controls[5].value/100);
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.useEQData = (document.getElementById('disabled-1').checked?true:false);
|
||||||
|
|
||||||
|
// radio buttons
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.useWaveformData=(document.getElementById('use-waveform').checked?true:false);
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.waveformDataOutside = document.getElementById('waveform-inside').checked?false:true;
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.eqDataOutside = document.getElementById('eq-inside').checked?false:true;
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.useAmplifier = (document.getElementById('use-amplifier').checked?true:false);
|
||||||
|
|
||||||
|
// threeSixtyPlayer.refreshCoords();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (threeSixtyPlayer.lastSound) {
|
||||||
|
|
||||||
|
threeSixtyPlayer.lastSound._360data.circleDiameter = self.controls[0].value;
|
||||||
|
|
||||||
|
threeSixtyPlayer.lastSound._360data.circleRadius = self.controls[0].value/2;
|
||||||
|
|
||||||
|
threeSixtyPlayer.lastSound._360data.waveformDataLineRatio = (self.controls[1].value/100)*2;
|
||||||
|
|
||||||
|
threeSixtyPlayer.lastSound._360data.waveformDataDownsample = (self.controls[2].value);
|
||||||
|
|
||||||
|
threeSixtyPlayer.lastSound._360data.eqDataLineRatio = parseInt((self.controls[3].value/100)*3*1000)/1000;
|
||||||
|
|
||||||
|
threeSixtyPlayer.lastSound._360data.eqDataDownsample = (self.controls[4].value);
|
||||||
|
|
||||||
|
threeSixtyPlayer.lastSound._360data.useEQData = (document.getElementById('disabled-1').checked?true:false);
|
||||||
|
|
||||||
|
// radio buttons
|
||||||
|
|
||||||
|
threeSixtyPlayer.lastSound._360data.useWaveformData=(document.getElementById('use-waveform').checked?true:false);
|
||||||
|
|
||||||
|
threeSixtyPlayer.lastSound._360data.waveformDataOutside = document.getElementById('waveform-inside').checked?false:true;
|
||||||
|
|
||||||
|
threeSixtyPlayer.lastSound._360data.eqDataOutside = document.getElementById('eq-inside').checked?false:true;
|
||||||
|
|
||||||
|
threeSixtyPlayer.lastSound._360data.useAmplifier = (document.getElementById('use-amplifier').checked?true:false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateExampleCode = function() {
|
||||||
|
// set innerHTML
|
||||||
|
document.getElementById('config-code').innerHTML = "\
|
||||||
|
// 360player.js, config section\n\
|
||||||
|
\n\
|
||||||
|
this.config = {\n\
|
||||||
|
\n\
|
||||||
|
playNext: <span>"+threeSixtyPlayer.config.playNext+"</span>,\n\
|
||||||
|
autoPlay: <span>"+threeSixtyPlayer.config.autoPlay+"</span>,\n\
|
||||||
|
allowMultiple: <span>"+threeSixtyPlayer.config.allowMultiple+"</span>,\n\
|
||||||
|
loadRingColor: <span>'"+threeSixtyPlayer.config.loadRingColor+"'</span>,\n\
|
||||||
|
playRingColor: <span>'"+threeSixtyPlayer.config.playRingColor+"'</span>,\n\
|
||||||
|
backgroundRingColor: <span>'"+threeSixtyPlayer.config.backgroundRingColor+"'</span>,\n\
|
||||||
|
circleDiameter: <span>"+threeSixtyPlayer.config.circleDiameter+"</span>,\n\
|
||||||
|
circleRadius: <span>"+threeSixtyPlayer.config.circleRadius+"</span>,\n\
|
||||||
|
animDuration: <span>"+threeSixtyPlayer.config.animDuration+"</span>,\n\
|
||||||
|
animTransition: <span>Animator.tx.bouncy</span>,\n\
|
||||||
|
showHMSTime: <span>"+threeSixtyPlayer.config.showHMSTime+"</span>,\n\
|
||||||
|
\n\
|
||||||
|
useWaveformData: <span>"+threeSixtyPlayer.config.useWaveformData+"</span>,\n\
|
||||||
|
waveformDataColor: <span>'"+threeSixtyPlayer.config.waveformDataColor+"'</span>,\n\
|
||||||
|
waveformDataDownsample: <span>"+threeSixtyPlayer.config.waveformDataDownsample+"</span>,\n\
|
||||||
|
waveformDataOutside: <span>"+threeSixtyPlayer.config.waveformDataOutside+"</span>,\n\
|
||||||
|
waveformDataConstrain: <span>false</span>,\n\
|
||||||
|
waveformDataLineRatio: <span>"+threeSixtyPlayer.config.waveformDataLineRatio+"</span>,\n\
|
||||||
|
\n\
|
||||||
|
useEQData: <span>"+threeSixtyPlayer.config.useEQData+"</span>,\n\
|
||||||
|
eqDataColor: <span>'"+threeSixtyPlayer.config.eqDataColor+"'</span>,\n\
|
||||||
|
eqDataDownsample: <span>"+threeSixtyPlayer.config.eqDataDownsample+"</span>,\n\
|
||||||
|
eqDataOutside: <span>"+threeSixtyPlayer.config.eqDataOutside+"</span>,\n\
|
||||||
|
eqDataLineRatio: <span>"+threeSixtyPlayer.config.eqDataLineRatio+"</span>,\n\
|
||||||
|
\n\
|
||||||
|
usePeakData: <span>"+threeSixtyPlayer.config.usePeakData+"</span>,\n\
|
||||||
|
peakDataColor: <span>'"+threeSixtyPlayer.config.peakDataColor+"'</span>,\n\
|
||||||
|
peakDataOutside: <span>"+threeSixtyPlayer.config.peakDataOutside+"</span>,\n\
|
||||||
|
peakDataLineRatio: <span>"+threeSixtyPlayer.config.peakDataLineRatio+"</span>,\n\
|
||||||
|
\n\
|
||||||
|
useAmplifier: <span>"+threeSixtyPlayer.config.useAmplifier+"</span>\n\
|
||||||
|
\n\
|
||||||
|
}";
|
||||||
|
document.getElementById('config-code').style.display = 'block'; // weird Fx fix
|
||||||
|
}
|
||||||
|
|
||||||
|
this.createCustomFirework = function() {
|
||||||
|
}
|
||||||
|
|
||||||
|
this.destructor = function() {
|
||||||
|
for (var i=self.controls.length; i--;) {
|
||||||
|
self.controls[i].destructor();
|
||||||
|
}
|
||||||
|
for (i=self.cb.length; i--;) {
|
||||||
|
self.cb.onclick = null;
|
||||||
|
self.cb[i] = null;
|
||||||
|
}
|
||||||
|
for (i=self.options.length; i--;) {
|
||||||
|
self.options[i] = null;
|
||||||
|
}
|
||||||
|
if (navigator.userAgent.match(/msie/i)) {
|
||||||
|
self.fbIE.onmouseover = null;
|
||||||
|
self.fbIE.onmouseout = null;
|
||||||
|
self.fbIE = null;
|
||||||
|
}
|
||||||
|
self.cb = null;
|
||||||
|
self.options = null;
|
||||||
|
self.controls = null;
|
||||||
|
self.functionExample = null;
|
||||||
|
self.o = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = parseInt(this.o.length/3);
|
||||||
|
for (var i=0; i<items; i++) {
|
||||||
|
this.controls[this.controls.length] = new Slider(this.o[(3*i)+2].getElementsByTagName('div')[1],this.o[(3*i)+1],this.o[(3*i)+2].getElementsByTagName('div')[0]);
|
||||||
|
}
|
||||||
|
this.cb = [document.getElementById('disabled-0'),document.getElementById('disabled-1')];
|
||||||
|
/*
|
||||||
|
for (i=this.cb.length; i--;) {
|
||||||
|
this.cb[i]._index = i;
|
||||||
|
this.cb[i].onclick = this.cbClick;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
this.options = [];
|
||||||
|
/*
|
||||||
|
this.cb[1].checked = false;
|
||||||
|
this.options = [document.getElementById('opt-random0'),document.getElementById('opt-random1')];
|
||||||
|
this.options[0].checked = false;
|
||||||
|
this.options[1].checked = true;
|
||||||
|
if (navigator.userAgent.match(/msie/i)) {
|
||||||
|
this.fbIE = document.getElementById('fireButton');
|
||||||
|
this.fbIE.onmouseover = function() {this.className='hover';}
|
||||||
|
this.fbIE.onmouseout = function() {this.className='';}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
// default values for controls
|
||||||
|
var values = [
|
||||||
|
256,
|
||||||
|
65,
|
||||||
|
40,
|
||||||
|
72,
|
||||||
|
48,
|
||||||
|
100
|
||||||
|
];
|
||||||
|
for (var i=0; i<values.length; i++) {
|
||||||
|
self.controls[i].setValue(values[i]); // defaults
|
||||||
|
}
|
||||||
|
},1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Slider(o,oV,oB) {
|
||||||
|
var self = this;
|
||||||
|
this.o = o;
|
||||||
|
this.oV = oV;
|
||||||
|
this.oB = oB;
|
||||||
|
this.scale = parseInt(oV.innerHTML.toString().substr(2));
|
||||||
|
this.oID = 'sc'+(gOID++);
|
||||||
|
this.offX = 0;
|
||||||
|
this.x = 0;
|
||||||
|
this.xMin = 0-10;
|
||||||
|
this.xMax = self.o.parentNode.offsetWidth-10;
|
||||||
|
this.value = 0;
|
||||||
|
this.timer = null;
|
||||||
|
this._className = this.o.className;
|
||||||
|
this.tween = [];
|
||||||
|
this.frame = 0;
|
||||||
|
|
||||||
|
this.over = function() {
|
||||||
|
this.className = self._className+' hover';
|
||||||
|
event.cancelBubble=true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.out = function() {
|
||||||
|
this.className = self._className;
|
||||||
|
event.cancelBubble=true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.down = function(e) {
|
||||||
|
var e = e?e:event;
|
||||||
|
self.offX = e.clientX-self.o.offsetLeft;
|
||||||
|
addEvent(document,'mousemove',self.move);
|
||||||
|
addEvent(document,'mouseup',self.up);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.barClick = function(e) {
|
||||||
|
var e=e?e:event;
|
||||||
|
self.slide(self.x,e.clientX-self.o.parentNode.parentNode.offsetLeft-self.o.offsetWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.move = function(e) {
|
||||||
|
var e=e?e:event;
|
||||||
|
var x = e.clientX-self.offX;
|
||||||
|
if (x>self.xMax) {
|
||||||
|
x = self.xMax;
|
||||||
|
} else if (x<self.xMin) {
|
||||||
|
x = self.xMin;
|
||||||
|
}
|
||||||
|
if (x != self.x) {
|
||||||
|
self.moveTo(x);
|
||||||
|
self.doUpdate();
|
||||||
|
controller.updateExample();
|
||||||
|
controller.updateExampleCode();
|
||||||
|
}
|
||||||
|
e.stopPropgation?e.stopPropagation():e.cancelBubble=true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.up = function(e) {
|
||||||
|
removeEvent(document,'mousemove',self.move);
|
||||||
|
removeEvent(document,'mouseup',self.up);
|
||||||
|
// controller.updateExample();
|
||||||
|
controller.updateExampleCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.slide = function(x0,x1) {
|
||||||
|
self.tween = mc.animator.createTween(x0,x1);
|
||||||
|
mc.animator.enqueue(self,self.animate,function(){
|
||||||
|
controller.updateExample()
|
||||||
|
controller.updateExampleCode();
|
||||||
|
});
|
||||||
|
mc.animator.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.moveTo = function(x) {
|
||||||
|
self.x = x;
|
||||||
|
self.o.style.marginLeft = x+'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.animate = function() {
|
||||||
|
self.moveTo(self.tween[self.frame].data);
|
||||||
|
self.doUpdate(50);
|
||||||
|
controller.updateExample();
|
||||||
|
if (self.frame++>=self.tween.length-1) {
|
||||||
|
self.active = false;
|
||||||
|
self.frame = 0;
|
||||||
|
if (self._oncomplete) self._oncomplete();
|
||||||
|
// self.doUpdate();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self.doUpdate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.doUpdate = function(t) {
|
||||||
|
// if (!self.timer) self.timer = setTimeout(self.update,t||20);
|
||||||
|
self.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.update = function() {
|
||||||
|
self.timer = null;
|
||||||
|
self.value = 1+parseInt(self.x/self.xMax*(self.scale-1));
|
||||||
|
if (self.value<1) self.value = 1;
|
||||||
|
// if (self.oV.innerHTML != self.value) self.oV.innerHTML = self.value;
|
||||||
|
// self.oV.innerHTML = self.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setValue = function(x) {
|
||||||
|
self.slide(self.x,Math.min(self.xMax,x));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.randomize = function() {
|
||||||
|
self.slide(self.x,parseInt(Math.random()*self.xMax));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.destructor = function() {
|
||||||
|
self.o.onmouseover = null;
|
||||||
|
self.o.onmouseout = null;
|
||||||
|
self.o.onmousedown = null;
|
||||||
|
self.o = null;
|
||||||
|
self.oV = null;
|
||||||
|
self.oB.onclick = null;
|
||||||
|
self.oB = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soundManager.isIE) {
|
||||||
|
// IE is lame, no :hover
|
||||||
|
this.o.onmouseover = this.over;
|
||||||
|
this.o.onmouseout = this.out;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.o.onmousedown = this.down;
|
||||||
|
this.oB.onclick = this.barClick;
|
||||||
|
self.update();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var gOID = 0;
|
||||||
|
|
||||||
|
function demoInit() {
|
||||||
|
controller = new Controller(document.getElementById('controls').getElementsByTagName('dd'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function demoDestuctor() {
|
||||||
|
controller.destructor();
|
||||||
|
controller = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var controller = null;
|
||||||
|
|
||||||
|
var mc = new MainController();
|
||||||
|
// create null objects if APIs not present
|
||||||
|
|
||||||
|
function createCP(oInput,oHandler) {
|
||||||
|
var Event = YAHOO.util.Event;
|
||||||
|
|
||||||
|
cpHandler = oHandler;
|
||||||
|
if (picker != null) {
|
||||||
|
// picker.showcontrols(true);
|
||||||
|
var c = oInput.value.substr(1);
|
||||||
|
picker.setValue(hex2decArray([c.substr(0,2),c.substr(2,2),c.substr(4,2)]),true); // be silent
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Event.onDOMReady(function() {
|
||||||
|
picker = new YAHOO.widget.ColorPicker("cp-container", {
|
||||||
|
showhsvcontrols: true,
|
||||||
|
showhexcontrols: true,
|
||||||
|
images: {
|
||||||
|
PICKER_THUMB: "../_image/picker_thumb.png",
|
||||||
|
HUE_THUMB: "../_image/hue_thumb.png"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// picker.showcontrols(false);
|
||||||
|
//a listener for logging RGB color changes;
|
||||||
|
//this will only be visible if logger is enabled:
|
||||||
|
var onRgbChange = function(o) {
|
||||||
|
/*o is an object
|
||||||
|
{ newValue: (array of R, G, B values),
|
||||||
|
prevValue: (array of R, G, B values),
|
||||||
|
type: "rgbChange"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
cpHandler(o.newValue);
|
||||||
|
controller.updateExampleCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
//subscribe to the rgbChange event;
|
||||||
|
picker.on("rgbChange", onRgbChange);
|
||||||
|
|
||||||
|
//use setValue to reset the value to white:
|
||||||
|
Event.on("reset", "click", function(e) {
|
||||||
|
picker.setValue([255, 255, 255], false); //false here means that rgbChange
|
||||||
|
//wil fire; true would silence it
|
||||||
|
});
|
||||||
|
|
||||||
|
//use the "get" method to get the current value
|
||||||
|
//of one of the Color Picker's properties; in
|
||||||
|
//this case, we'll get the hex value and write it
|
||||||
|
//to the log:
|
||||||
|
Event.on("gethex", "click", function(e) {
|
||||||
|
console.log("Current hex value: " + picker.get("hex"));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var picker = null;
|
||||||
|
|
||||||
|
cpHandler = function() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// hex -> dec / dec -> hex
|
||||||
|
// http://www.southwest.com.au/~jfuller/binary/converter.htm
|
||||||
|
|
||||||
|
function dec2hex(cval) {
|
||||||
|
if (cval > 255) cval = 255;
|
||||||
|
var hexascii = "0123456789ABCDEF";
|
||||||
|
var cval0 = Math.floor(cval/16);
|
||||||
|
var cval1 = cval-(cval0*16);
|
||||||
|
var c1 = hexascii.charAt(cval0);
|
||||||
|
var c2 = hexascii.charAt(cval1);
|
||||||
|
return (c1+c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hex2dec(cval) {
|
||||||
|
cval = cval.toUpperCase();
|
||||||
|
var tval = 0;
|
||||||
|
var hexascii = "0123456789ABCDEF";
|
||||||
|
var mychar, ch;
|
||||||
|
for (var c=0; c<cval.length; c++) {
|
||||||
|
mychar = cval.charAt(c);
|
||||||
|
for (ch=0; ch<16; ch++) {
|
||||||
|
if (mychar == hexascii.charAt(ch)) {
|
||||||
|
tval += ch;
|
||||||
|
if (c<cval.length-1) tval *= 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tval;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hex2decArray(hArray) {
|
||||||
|
var result = [];
|
||||||
|
for (var i=0,j=hArray.length; i<j; i++) {
|
||||||
|
result[i] = hex2dec(hArray[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dec2hexArray(dArray) {
|
||||||
|
var result = [];
|
||||||
|
for (var i=0,j=dArray.length; i<j; i++) {
|
||||||
|
result[i] = dec2hex(dArray[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.waveformDataColor = '#'+dec2hexArray([self.controls[5].value,self.controls[6].value,self.controls[7].value]).join('');
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.eqDataColor = '#'+dec2hexArray([self.controls[8].value,self.controls[9].value,self.controls[10].value]).join('');
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.loadRingColor = '#'+dec2hexArray([self.controls[11].value,self.controls[12].value,self.controls[13].value]).join('');
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.playRingColor = '#'+dec2hexArray([self.controls[14].value,self.controls[15].value,self.controls[16].value]).join('');
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.waveformDataLineRatio = (self.controls[1].value/100)*2;
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.waveformDataDownsample = (self.controls[2].value);
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.eqDataLineRatio = (self.controls[3].value/100)*3;
|
||||||
|
|
||||||
|
threeSixtyPlayer.config.eqDataDownsample = (self.controls[4].value);
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
function _id(sID) {
|
||||||
|
return document.getElementById(sID);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setWaveformColor(sColor) {
|
||||||
|
var value = '#'+(dec2hexArray(sColor).join(''));
|
||||||
|
threeSixtyPlayer.config.waveformDataColor = value;
|
||||||
|
_id('waveform-color').value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setEQColor(sColor) {
|
||||||
|
var value = '#'+dec2hexArray(sColor).join('');
|
||||||
|
_id('eq-color').value = value;
|
||||||
|
threeSixtyPlayer.config.eqDataColor = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLoadedRingColor(sColor) {
|
||||||
|
var value = '#'+dec2hexArray(sColor).join('');
|
||||||
|
_id('loaded-ring-color').value = value;
|
||||||
|
threeSixtyPlayer.config.loadRingColor = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setProgressRingColor(sColor) {
|
||||||
|
var value = '#'+dec2hexArray(sColor).join('');
|
||||||
|
_id('progress-ring-color').value = value;
|
||||||
|
threeSixtyPlayer.config.playRingColor = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBackgroundRingColor(sColor) {
|
||||||
|
var value = '#'+dec2hexArray(sColor).join('');
|
||||||
|
_id('bg-ring-color').value = value;
|
||||||
|
threeSixtyPlayer.config.backgroundRingColor = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addEvent(o,evtName,evtHandler) {
|
||||||
|
typeof window.addEventListener !== 'undefined' ? o.addEventListener(evtName,evtHandler,false) : o.attachEvent('on'+evtName,evtHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeEvent(o,evtName,evtHandler) {
|
||||||
|
typeof window.removeEventListener !== 'undefined' ? o.removeEventListener(evtName,evtHandler,false) : o.detachEvent('on'+evtName,evtHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.location.toString().match(/#customize/i)) {
|
||||||
|
addEvent(window,'resize',mc.getWindowCoords);
|
||||||
|
addEvent(window,'scroll',mc.getWindowCoords);
|
||||||
|
addEvent(window,'load',mc.init);
|
||||||
|
addEvent(window,'load',demoInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.location.toString().match(/hifi/i)) {
|
||||||
|
soundManager.onready(function(){
|
||||||
|
document.getElementById('hifi').style.display = 'none';
|
||||||
|
|
||||||
|
threeSixtyPlayer.config = {
|
||||||
|
|
||||||
|
playNext: false,
|
||||||
|
autoPlay: false,
|
||||||
|
loadRingColor: '#ccc',
|
||||||
|
playRingColor: '#000',
|
||||||
|
backgroundRingColor: '#eee',
|
||||||
|
circleDiameter: 256,
|
||||||
|
circleRadius: 128,
|
||||||
|
animDuration: 500,
|
||||||
|
animTransition: Animator.tx.bouncy,
|
||||||
|
showHMSTime: true,
|
||||||
|
|
||||||
|
useWaveformData: true,
|
||||||
|
waveformDataColor: '#0099ff',
|
||||||
|
waveformDataDownsample: 1,
|
||||||
|
waveformDataOutside: true,
|
||||||
|
waveformDataConstrain: false,
|
||||||
|
waveformDataLineRatio: 0.56,
|
||||||
|
|
||||||
|
useEQData: true,
|
||||||
|
eqDataColor: '#339933',
|
||||||
|
eqDataDownsample: 1,
|
||||||
|
eqDataOutside: true,
|
||||||
|
eqDataLineRatio: 0.72,
|
||||||
|
|
||||||
|
usePeakData: true,
|
||||||
|
peakDataColor: '#ff33ff',
|
||||||
|
peakDataOutside: true,
|
||||||
|
peakDataLineRatio: 0.5,
|
||||||
|
scaleArcWidth: 1, // thickness factor of playback progress ring
|
||||||
|
useAmplifier: true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**
|
||||||
|
* In-page demo CSS - see external CSS for actual relevant stuff.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#soundmanager-debug {
|
||||||
|
/* SM2 debug container (optional, makes debug more useable) */
|
||||||
|
position:absolute;position:fixed;*position:absolute;bottom:10px;right:10px;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font:75% normal verdana,arial,tahoma,"sans serif";
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3 {
|
||||||
|
font:3em arial,tahoma,verdana;
|
||||||
|
font-weight:normal;
|
||||||
|
margin-bottom:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-top:0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2 {
|
||||||
|
letter-spacing: -0.005em; /* zomg web x.0! ;) */
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size:2em;
|
||||||
|
margin-top:0px;
|
||||||
|
margin-bottom:0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size:1.5em;
|
||||||
|
margin-bottom:1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 a,
|
||||||
|
h1 a:hover {
|
||||||
|
color:#000;
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 a:hover {
|
||||||
|
text-decoration:underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.notes {
|
||||||
|
margin-left:0px;
|
||||||
|
padding-left:1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note {
|
||||||
|
margin-top:0px;
|
||||||
|
font-style:italic;
|
||||||
|
color:#999;
|
||||||
|
margin-bottom:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left {
|
||||||
|
max-width:56em;
|
||||||
|
margin-left:1em;
|
||||||
|
}
|
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 493 B |
After Width: | Height: | Size: 2.4 KiB |
|
@ -0,0 +1,173 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||||
|
<head>
|
||||||
|
<title>360° MP3 player UI demo (SoundManager 2)</title>
|
||||||
|
<meta name="robots" content="noindex" />
|
||||||
|
<meta name="description" content="Javascript-driven sound, canvas-based MP3 player UI demo: 360-degree circular control / jog wheel example for playing MP3 links using SoundManager 2, Javascript and Canvas.">
|
||||||
|
|
||||||
|
<!-- required -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="360player.css" />
|
||||||
|
|
||||||
|
<!-- special IE-only canvas fix -->
|
||||||
|
<!--[if IE]><script type="text/javascript" src="script/excanvas.js"></script><![endif]-->
|
||||||
|
|
||||||
|
<!-- Apache-licensed animation library -->
|
||||||
|
<script type="text/javascript" src="script/berniecode-animator.js"></script>
|
||||||
|
|
||||||
|
<!-- the core stuff -->
|
||||||
|
<script type="text/javascript" src="../../script/soundmanager2.js"></script>
|
||||||
|
<script type="text/javascript" src="script/360player.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
soundManager.setup({
|
||||||
|
// path to directory containing SM2 SWF
|
||||||
|
url: '../../swf/'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- stuff you don't need -->
|
||||||
|
<!-- makes the fonts nicer etc. -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="../index.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="demo.css" />
|
||||||
|
|
||||||
|
<!-- soundManager.useFlashBlock: related CSS -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
/* Demo page, general layout */
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left {
|
||||||
|
position:relative;
|
||||||
|
width:950px;
|
||||||
|
max-width:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left h2 {
|
||||||
|
padding-top:0px;
|
||||||
|
margin-bottom:0.25em;
|
||||||
|
color:#666;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.block {
|
||||||
|
margin-top:0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="left">
|
||||||
|
|
||||||
|
<h1><a href="http://www.schillmania.com/projects/soundmanager2/" title="Javascript MP3 player project home">SoundManager 2</a> / <a href="http://schillmania.com/projects/soundmanager2/demo/360-player/">360° Player</a>: JavaScript + Canvas UI</h1>
|
||||||
|
|
||||||
|
<p class="note" style="color:#666;margin-top:0.5em;margin-bottom:0.5em">Canvas-based UI. Load progress, seek, play/pause etc. Also see <a href="canvas-visualization.html" title="Javascript canvas visualization with waveform/eq data">360° UI visualization</a> demo.</p>
|
||||||
|
|
||||||
|
<div id="sm2-container">
|
||||||
|
<!-- flash movie is added here -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top:1.25em">
|
||||||
|
|
||||||
|
<div style="float:left;display:inline;min-width:200px"> <!-- float is just for this demo layout, you don't need it. -->
|
||||||
|
|
||||||
|
<div class="ui360" style="margin-top:-0.55em"><a href="../_mp3/rain.mp3">Rain</a></div>
|
||||||
|
|
||||||
|
<div class="ui360"><a href="http://freshly-ground.com/data/audio/mpc/20090119%20-%20Untitled%20Groove.mp3">20090119 - Untitled Groove</a></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="float:left;display:inline;margin-left:40px;border-left:1px solid #ccc;padding-left:30px;width:152px">
|
||||||
|
|
||||||
|
<p style="margin-top:1em;margin-bottom:0px">Alternate style: inline</p>
|
||||||
|
|
||||||
|
<div class="sm2-inline-list" style="margin-bottom:10px"> <!-- note the CSS class, changes the layout -->
|
||||||
|
|
||||||
|
<div class="ui360"><a href="http://www.freshly-ground.com/data/audio/binaural/Mak.mp3">Angry cow sound?</a></div>
|
||||||
|
<div class="ui360"><a href="http://www.freshly-ground.com/data/audio/binaural/Things that open, close and roll.mp3">Things that open, close and roll</a></div>
|
||||||
|
<div class="ui360"><a href="http://www.freshly-ground.com/misc/music/20060826%20-%20Armstrong.mp3">20060826 - Armstrong</a></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="clear:both"></div>
|
||||||
|
|
||||||
|
|
||||||
|
<h3>How This Works</h3>
|
||||||
|
|
||||||
|
<p>The script looks for a container element matching <code>div.<span>ui360</span></code>, and then the first link inside of it.</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<pre class="block"><code><div class="<span>ui360</span>">
|
||||||
|
<a href="/path/to/an.mp3">play "an.mp3"</a>
|
||||||
|
</div></code></pre>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>When the 360 player script loads, it adds a <code>UI</code> template to the block, prepending it in front of the MP3 link:</p>
|
||||||
|
|
||||||
|
<pre class="block"><code><div class="<span>ui360</span>">
|
||||||
|
<span><span><-- dynamically-inserted block --></span></span>
|
||||||
|
<div class="<span>ui</span>">
|
||||||
|
<canvas class="<span>sm2-canvas</span>"></canvas>
|
||||||
|
<span class="<span>sm2-360btn</span>"></span>
|
||||||
|
<div class="<span>sm2-timing</span>"></div>
|
||||||
|
<div class="<span>sm2-cover</span>"></div>
|
||||||
|
</div>
|
||||||
|
<span><span><-- /UI --></span></span>
|
||||||
|
<a href="<span>/path/to/an.mp3</span>">
|
||||||
|
</div></code></pre>
|
||||||
|
|
||||||
|
<h3>Customizing the UI</h3>
|
||||||
|
|
||||||
|
<p>The player's default 50x50-pixel canvas is defined both within JavaScript and CSS. For an example with different values, see this <a href="canvas-visualization.html" title="360° UI: larger version">larger version</a>.</p>
|
||||||
|
|
||||||
|
<pre class="block"><code>threeSixtyPlayer.config = {
|
||||||
|
playNext: <span>false</span>, <span><span>// stop after one sound, or play through list until end</span></span>
|
||||||
|
autoPlay: <span>false</span>, <span><span>// start playing the first sound right away</span></span>
|
||||||
|
allowMultiple: <span>true</span>, <span><span>// let many sounds play at once (false = one at a time)</span></span>
|
||||||
|
loadRingColor: <span>'#ccc',</span> <span><span>// amount of sound which has loaded</span></span>
|
||||||
|
playRingColor: <span>'#000'</span>, <span><span>// amount of sound which has played</span></span>
|
||||||
|
backgroundRingColor: <span>'#eee', </span><span><span>// "default" color shown underneath everything else</span></span>
|
||||||
|
animDuration: <span>500</span>,
|
||||||
|
animTransition: <span>Animator.tx.bouncy</span> <span><span>// http://www.berniecode.com/writing/animator.html</span></span>
|
||||||
|
}</code></pre>
|
||||||
|
|
||||||
|
<p>The CSS for the canvas UI block is a bit ugly, but JavaScript reads the width of the <code>.sm2-360ui</code> element in the DOM as set by CSS and uses that to later draw and update the canvas element while playing.</p>
|
||||||
|
|
||||||
|
<pre class="block"><code>.ui360,
|
||||||
|
.sm2-360ui {
|
||||||
|
<span><span>/* size of the container for the circle, etc. */</span></span>
|
||||||
|
width:<span>50px</span>;
|
||||||
|
height:<span>50px</span>;
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<h3>Third-party Components</h3>
|
||||||
|
|
||||||
|
<p>This demo includes use of <a href="http://www.berniecode.com/writing/animator.html">Bernie's Better Animation Class</a> (Apache licensed) for some animation effects.</p>
|
||||||
|
<p>Also, some loader/spinner icons from <a href="http://ajaxload.info">ajaxload.info</a> are used for showing loading/buffering states.</p>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 home">SoundManager 2 project page</a> (not an MP3 link)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,674 @@
|
||||||
|
/** @license
|
||||||
|
Animator.js 1.1.9
|
||||||
|
|
||||||
|
This library is released under the BSD license:
|
||||||
|
|
||||||
|
Copyright (c) 2006, Bernard Sumption. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer. Redistributions in binary
|
||||||
|
form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
the following disclaimer in the documentation and/or other materials
|
||||||
|
provided with the distribution. Neither the name BernieCode nor
|
||||||
|
the names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// http://www.berniecode.com/writing/animator.html
|
||||||
|
|
||||||
|
// Applies a sequence of numbers between 0 and 1 to a number of subjects
|
||||||
|
// construct - see setOptions for parameters
|
||||||
|
function Animator(options) {
|
||||||
|
this.setOptions(options);
|
||||||
|
var _this = this;
|
||||||
|
this.timerDelegate = function(){_this.onTimerEvent()};
|
||||||
|
this.subjects = [];
|
||||||
|
this.subjectScopes = [];
|
||||||
|
this.target = 0;
|
||||||
|
this.state = 0;
|
||||||
|
this.lastTime = null;
|
||||||
|
};
|
||||||
|
Animator.prototype = {
|
||||||
|
// apply defaults
|
||||||
|
setOptions: function(options) {
|
||||||
|
this.options = Animator.applyDefaults({
|
||||||
|
interval: 20, // time between animation frames
|
||||||
|
duration: 400, // length of animation
|
||||||
|
onComplete: function(){},
|
||||||
|
onStep: function(){},
|
||||||
|
transition: Animator.tx.easeInOut
|
||||||
|
}, options);
|
||||||
|
},
|
||||||
|
// animate from the current state to provided value
|
||||||
|
seekTo: function(to) {
|
||||||
|
this.seekFromTo(this.state, to);
|
||||||
|
},
|
||||||
|
// animate from the current state to provided value
|
||||||
|
seekFromTo: function(from, to) {
|
||||||
|
this.target = Math.max(0, Math.min(1, to));
|
||||||
|
this.state = Math.max(0, Math.min(1, from));
|
||||||
|
this.lastTime = new Date().getTime();
|
||||||
|
if (!this.intervalId) {
|
||||||
|
this.intervalId = window.setInterval(this.timerDelegate, this.options.interval);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// animate from the current state to provided value
|
||||||
|
jumpTo: function(to) {
|
||||||
|
this.target = this.state = Math.max(0, Math.min(1, to));
|
||||||
|
this.propagate();
|
||||||
|
},
|
||||||
|
// seek to the opposite of the current target
|
||||||
|
toggle: function() {
|
||||||
|
this.seekTo(1 - this.target);
|
||||||
|
},
|
||||||
|
// add a function or an object with a method setState(state) that will be called with a number
|
||||||
|
// between 0 and 1 on each frame of the animation
|
||||||
|
addSubject: function(subject,scope) {
|
||||||
|
this.subjects[this.subjects.length] = subject;
|
||||||
|
this.subjectScopes[this.subjectScopes.length] = scope;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
// remove all subjects
|
||||||
|
clearSubjects: function() {
|
||||||
|
this.subjects = [];
|
||||||
|
this.subjectScopes = [];
|
||||||
|
},
|
||||||
|
// forward the current state to the animation subjects
|
||||||
|
propagate: function() {
|
||||||
|
var value = this.options.transition(this.state);
|
||||||
|
for (var i=0; i<this.subjects.length; i++) {
|
||||||
|
if (this.subjects[i].setState) {
|
||||||
|
this.subjects[i].setState(value);
|
||||||
|
} else {
|
||||||
|
this.subjects[i].apply(this.subjectScopes[i],[value]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// called once per frame to update the current state
|
||||||
|
onTimerEvent: function() {
|
||||||
|
var now = new Date().getTime();
|
||||||
|
var timePassed = now - this.lastTime;
|
||||||
|
this.lastTime = now;
|
||||||
|
var movement = (timePassed / this.options.duration) * (this.state < this.target ? 1 : -1);
|
||||||
|
if (Math.abs(movement) >= Math.abs(this.state - this.target)) {
|
||||||
|
this.state = this.target;
|
||||||
|
} else {
|
||||||
|
this.state += movement;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.propagate();
|
||||||
|
} finally {
|
||||||
|
this.options.onStep.call(this);
|
||||||
|
if (this.target == this.state) {
|
||||||
|
window.clearInterval(this.intervalId);
|
||||||
|
this.intervalId = null;
|
||||||
|
this.options.onComplete.call(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// shortcuts
|
||||||
|
play: function() {this.seekFromTo(0, 1)},
|
||||||
|
reverse: function() {this.seekFromTo(1, 0)},
|
||||||
|
// return a string describing this Animator, for debugging
|
||||||
|
inspect: function() {
|
||||||
|
var str = "#<Animator:\n";
|
||||||
|
for (var i=0; i<this.subjects.length; i++) {
|
||||||
|
str += this.subjects[i].inspect();
|
||||||
|
}
|
||||||
|
str += ">";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// merge the properties of two objects
|
||||||
|
Animator.applyDefaults = function(defaults, prefs) {
|
||||||
|
prefs = prefs || {};
|
||||||
|
var prop, result = {};
|
||||||
|
for (prop in defaults) result[prop] = prefs[prop] !== undefined ? prefs[prop] : defaults[prop];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// make an array from any object
|
||||||
|
Animator.makeArray = function(o) {
|
||||||
|
if (o == null) return [];
|
||||||
|
if (!o.length) return [o];
|
||||||
|
var result = [];
|
||||||
|
for (var i=0; i<o.length; i++) result[i] = o[i];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// convert a dash-delimited-property to a camelCaseProperty (c/o Prototype, thanks Sam!)
|
||||||
|
Animator.camelize = function(string) {
|
||||||
|
var oStringList = string.split('-');
|
||||||
|
if (oStringList.length == 1) return oStringList[0];
|
||||||
|
|
||||||
|
var camelizedString = string.indexOf('-') == 0
|
||||||
|
? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
|
||||||
|
: oStringList[0];
|
||||||
|
|
||||||
|
for (var i = 1, len = oStringList.length; i < len; i++) {
|
||||||
|
var s = oStringList[i];
|
||||||
|
camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
|
||||||
|
}
|
||||||
|
return camelizedString;
|
||||||
|
}
|
||||||
|
// syntactic sugar for creating CSSStyleSubjects
|
||||||
|
Animator.apply = function(el, style, options) {
|
||||||
|
if (style instanceof Array) {
|
||||||
|
return new Animator(options).addSubject(new CSSStyleSubject(el, style[0], style[1]));
|
||||||
|
}
|
||||||
|
return new Animator(options).addSubject(new CSSStyleSubject(el, style));
|
||||||
|
}
|
||||||
|
// make a transition function that gradually accelerates. pass a=1 for smooth
|
||||||
|
// gravitational acceleration, higher values for an exaggerated effect
|
||||||
|
Animator.makeEaseIn = function(a) {
|
||||||
|
return function(state) {
|
||||||
|
return Math.pow(state, a*2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// as makeEaseIn but for deceleration
|
||||||
|
Animator.makeEaseOut = function(a) {
|
||||||
|
return function(state) {
|
||||||
|
return 1 - Math.pow(1 - state, a*2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// make a transition function that, like an object with momentum being attracted to a point,
|
||||||
|
// goes past the target then returns
|
||||||
|
Animator.makeElastic = function(bounces) {
|
||||||
|
return function(state) {
|
||||||
|
state = Animator.tx.easeInOut(state);
|
||||||
|
return ((1-Math.cos(state * Math.PI * bounces)) * (1 - state)) + state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// make an Attack Decay Sustain Release envelope that starts and finishes on the same level
|
||||||
|
//
|
||||||
|
Animator.makeADSR = function(attackEnd, decayEnd, sustainEnd, sustainLevel) {
|
||||||
|
if (sustainLevel == null) sustainLevel = 0.5;
|
||||||
|
return function(state) {
|
||||||
|
if (state < attackEnd) {
|
||||||
|
return state / attackEnd;
|
||||||
|
}
|
||||||
|
if (state < decayEnd) {
|
||||||
|
return 1 - ((state - attackEnd) / (decayEnd - attackEnd) * (1 - sustainLevel));
|
||||||
|
}
|
||||||
|
if (state < sustainEnd) {
|
||||||
|
return sustainLevel;
|
||||||
|
}
|
||||||
|
return sustainLevel * (1 - ((state - sustainEnd) / (1 - sustainEnd)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// make a transition function that, like a ball falling to floor, reaches the target and/
|
||||||
|
// bounces back again
|
||||||
|
Animator.makeBounce = function(bounces) {
|
||||||
|
var fn = Animator.makeElastic(bounces);
|
||||||
|
return function(state) {
|
||||||
|
state = fn(state);
|
||||||
|
return state <= 1 ? state : 2-state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pre-made transition functions to use with the 'transition' option
|
||||||
|
Animator.tx = {
|
||||||
|
easeInOut: function(pos){
|
||||||
|
return ((-Math.cos(pos*Math.PI)/2) + 0.5);
|
||||||
|
},
|
||||||
|
linear: function(x) {
|
||||||
|
return x;
|
||||||
|
},
|
||||||
|
easeIn: Animator.makeEaseIn(1.5),
|
||||||
|
easeOut: Animator.makeEaseOut(1.5),
|
||||||
|
strongEaseIn: Animator.makeEaseIn(2.5),
|
||||||
|
strongEaseOut: Animator.makeEaseOut(2.5),
|
||||||
|
elastic: Animator.makeElastic(1),
|
||||||
|
veryElastic: Animator.makeElastic(3),
|
||||||
|
bouncy: Animator.makeBounce(1),
|
||||||
|
veryBouncy: Animator.makeBounce(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
// animates a pixel-based style property between two integer values
|
||||||
|
function NumericalStyleSubject(els, property, from, to, units) {
|
||||||
|
this.els = Animator.makeArray(els);
|
||||||
|
if (property == 'opacity' && window.ActiveXObject) {
|
||||||
|
this.property = 'filter';
|
||||||
|
} else {
|
||||||
|
this.property = Animator.camelize(property);
|
||||||
|
}
|
||||||
|
this.from = parseFloat(from);
|
||||||
|
this.to = parseFloat(to);
|
||||||
|
this.units = units != null ? units : 'px';
|
||||||
|
}
|
||||||
|
NumericalStyleSubject.prototype = {
|
||||||
|
setState: function(state) {
|
||||||
|
var style = this.getStyle(state);
|
||||||
|
var visibility = (this.property == 'opacity' && state == 0) ? 'hidden' : '';
|
||||||
|
var j=0;
|
||||||
|
for (var i=0; i<this.els.length; i++) {
|
||||||
|
try {
|
||||||
|
this.els[i].style[this.property] = style;
|
||||||
|
} catch (e) {
|
||||||
|
// ignore fontWeight - intermediate numerical values cause exeptions in firefox
|
||||||
|
if (this.property != 'fontWeight') throw e;
|
||||||
|
}
|
||||||
|
if (j++ > 20) return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getStyle: function(state) {
|
||||||
|
state = this.from + ((this.to - this.from) * state);
|
||||||
|
if (this.property == 'filter') return "alpha(opacity=" + Math.round(state*100) + ")";
|
||||||
|
if (this.property == 'opacity') return state;
|
||||||
|
return Math.round(state) + this.units;
|
||||||
|
},
|
||||||
|
inspect: function() {
|
||||||
|
return "\t" + this.property + "(" + this.from + this.units + " to " + this.to + this.units + ")\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// animates a colour based style property between two hex values
|
||||||
|
function ColorStyleSubject(els, property, from, to) {
|
||||||
|
this.els = Animator.makeArray(els);
|
||||||
|
this.property = Animator.camelize(property);
|
||||||
|
this.to = this.expandColor(to);
|
||||||
|
this.from = this.expandColor(from);
|
||||||
|
this.origFrom = from;
|
||||||
|
this.origTo = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorStyleSubject.prototype = {
|
||||||
|
// parse "#FFFF00" to [256, 256, 0]
|
||||||
|
expandColor: function(color) {
|
||||||
|
var hexColor, red, green, blue;
|
||||||
|
hexColor = ColorStyleSubject.parseColor(color);
|
||||||
|
if (hexColor) {
|
||||||
|
red = parseInt(hexColor.slice(1, 3), 16);
|
||||||
|
green = parseInt(hexColor.slice(3, 5), 16);
|
||||||
|
blue = parseInt(hexColor.slice(5, 7), 16);
|
||||||
|
return [red,green,blue]
|
||||||
|
}
|
||||||
|
if (window.DEBUG) {
|
||||||
|
alert("Invalid colour: '" + color + "'");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getValueForState: function(color, state) {
|
||||||
|
return Math.round(this.from[color] + ((this.to[color] - this.from[color]) * state));
|
||||||
|
},
|
||||||
|
setState: function(state) {
|
||||||
|
var color = '#'
|
||||||
|
+ ColorStyleSubject.toColorPart(this.getValueForState(0, state))
|
||||||
|
+ ColorStyleSubject.toColorPart(this.getValueForState(1, state))
|
||||||
|
+ ColorStyleSubject.toColorPart(this.getValueForState(2, state));
|
||||||
|
for (var i=0; i<this.els.length; i++) {
|
||||||
|
this.els[i].style[this.property] = color;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inspect: function() {
|
||||||
|
return "\t" + this.property + "(" + this.origFrom + " to " + this.origTo + ")\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return a properly formatted 6-digit hex colour spec, or false
|
||||||
|
ColorStyleSubject.parseColor = function(string) {
|
||||||
|
var color = '#', match;
|
||||||
|
if(match = ColorStyleSubject.parseColor.rgbRe.exec(string)) {
|
||||||
|
var part;
|
||||||
|
for (var i=1; i<=3; i++) {
|
||||||
|
part = Math.max(0, Math.min(255, parseInt(match[i])));
|
||||||
|
color += ColorStyleSubject.toColorPart(part);
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
if (match = ColorStyleSubject.parseColor.hexRe.exec(string)) {
|
||||||
|
if(match[1].length == 3) {
|
||||||
|
for (var i=0; i<3; i++) {
|
||||||
|
color += match[1].charAt(i) + match[1].charAt(i);
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
return '#' + match[1];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// convert a number to a 2 digit hex string
|
||||||
|
ColorStyleSubject.toColorPart = function(number) {
|
||||||
|
if (number > 255) number = 255;
|
||||||
|
var digits = number.toString(16);
|
||||||
|
if (number < 16) return '0' + digits;
|
||||||
|
return digits;
|
||||||
|
}
|
||||||
|
ColorStyleSubject.parseColor.rgbRe = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i;
|
||||||
|
ColorStyleSubject.parseColor.hexRe = /^\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
||||||
|
|
||||||
|
// Animates discrete styles, i.e. ones that do not scale but have discrete values
|
||||||
|
// that can't be interpolated
|
||||||
|
function DiscreteStyleSubject(els, property, from, to, threshold) {
|
||||||
|
this.els = Animator.makeArray(els);
|
||||||
|
this.property = Animator.camelize(property);
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
this.threshold = threshold || 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscreteStyleSubject.prototype = {
|
||||||
|
setState: function(state) {
|
||||||
|
var j=0;
|
||||||
|
for (var i=0; i<this.els.length; i++) {
|
||||||
|
this.els[i].style[this.property] = state <= this.threshold ? this.from : this.to;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inspect: function() {
|
||||||
|
return "\t" + this.property + "(" + this.from + " to " + this.to + " @ " + this.threshold + ")\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// animates between two styles defined using CSS.
|
||||||
|
// if style1 and style2 are present, animate between them, if only style1
|
||||||
|
// is present, animate between the element's current style and style1
|
||||||
|
function CSSStyleSubject(els, style1, style2) {
|
||||||
|
els = Animator.makeArray(els);
|
||||||
|
this.subjects = [];
|
||||||
|
if (els.length == 0) return;
|
||||||
|
var prop, toStyle, fromStyle;
|
||||||
|
if (style2) {
|
||||||
|
fromStyle = this.parseStyle(style1, els[0]);
|
||||||
|
toStyle = this.parseStyle(style2, els[0]);
|
||||||
|
} else {
|
||||||
|
toStyle = this.parseStyle(style1, els[0]);
|
||||||
|
fromStyle = {};
|
||||||
|
for (prop in toStyle) {
|
||||||
|
fromStyle[prop] = CSSStyleSubject.getStyle(els[0], prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// remove unchanging properties
|
||||||
|
var prop;
|
||||||
|
for (prop in fromStyle) {
|
||||||
|
if (fromStyle[prop] == toStyle[prop]) {
|
||||||
|
delete fromStyle[prop];
|
||||||
|
delete toStyle[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// discover the type (numerical or colour) of each style
|
||||||
|
var prop, units, match, type, from, to;
|
||||||
|
for (prop in fromStyle) {
|
||||||
|
var fromProp = String(fromStyle[prop]);
|
||||||
|
var toProp = String(toStyle[prop]);
|
||||||
|
if (toStyle[prop] == null) {
|
||||||
|
if (window.DEBUG) alert("No to style provided for '" + prop + '"');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from = ColorStyleSubject.parseColor(fromProp)) {
|
||||||
|
to = ColorStyleSubject.parseColor(toProp);
|
||||||
|
type = ColorStyleSubject;
|
||||||
|
} else if (fromProp.match(CSSStyleSubject.numericalRe)
|
||||||
|
&& toProp.match(CSSStyleSubject.numericalRe)) {
|
||||||
|
from = parseFloat(fromProp);
|
||||||
|
to = parseFloat(toProp);
|
||||||
|
type = NumericalStyleSubject;
|
||||||
|
match = CSSStyleSubject.numericalRe.exec(fromProp);
|
||||||
|
var reResult = CSSStyleSubject.numericalRe.exec(toProp);
|
||||||
|
if (match[1] != null) {
|
||||||
|
units = match[1];
|
||||||
|
} else if (reResult[1] != null) {
|
||||||
|
units = reResult[1];
|
||||||
|
} else {
|
||||||
|
units = reResult;
|
||||||
|
}
|
||||||
|
} else if (fromProp.match(CSSStyleSubject.discreteRe)
|
||||||
|
&& toProp.match(CSSStyleSubject.discreteRe)) {
|
||||||
|
from = fromProp;
|
||||||
|
to = toProp;
|
||||||
|
type = DiscreteStyleSubject;
|
||||||
|
units = 0; // hack - how to get an animator option down to here
|
||||||
|
} else {
|
||||||
|
if (window.DEBUG) {
|
||||||
|
alert("Unrecognised format for value of "
|
||||||
|
+ prop + ": '" + fromStyle[prop] + "'");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.subjects[this.subjects.length] = new type(els, prop, from, to, units);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CSSStyleSubject.prototype = {
|
||||||
|
// parses "width: 400px; color: #FFBB2E" to {width: "400px", color: "#FFBB2E"}
|
||||||
|
parseStyle: function(style, el) {
|
||||||
|
var rtn = {};
|
||||||
|
// if style is a rule set
|
||||||
|
if (style.indexOf(":") != -1) {
|
||||||
|
var styles = style.split(";");
|
||||||
|
for (var i=0; i<styles.length; i++) {
|
||||||
|
var parts = CSSStyleSubject.ruleRe.exec(styles[i]);
|
||||||
|
if (parts) {
|
||||||
|
rtn[parts[1]] = parts[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// else assume style is a class name
|
||||||
|
else {
|
||||||
|
var prop, value, oldClass;
|
||||||
|
oldClass = el.className;
|
||||||
|
el.className = style;
|
||||||
|
for (var i=0; i<CSSStyleSubject.cssProperties.length; i++) {
|
||||||
|
prop = CSSStyleSubject.cssProperties[i];
|
||||||
|
value = CSSStyleSubject.getStyle(el, prop);
|
||||||
|
if (value != null) {
|
||||||
|
rtn[prop] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
el.className = oldClass;
|
||||||
|
}
|
||||||
|
return rtn;
|
||||||
|
|
||||||
|
},
|
||||||
|
setState: function(state) {
|
||||||
|
for (var i=0; i<this.subjects.length; i++) {
|
||||||
|
this.subjects[i].setState(state);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inspect: function() {
|
||||||
|
var str = "";
|
||||||
|
for (var i=0; i<this.subjects.length; i++) {
|
||||||
|
str += this.subjects[i].inspect();
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// get the current value of a css property,
|
||||||
|
CSSStyleSubject.getStyle = function(el, property){
|
||||||
|
var style;
|
||||||
|
if(document.defaultView && document.defaultView.getComputedStyle){
|
||||||
|
style = document.defaultView.getComputedStyle(el, "").getPropertyValue(property);
|
||||||
|
if (style) {
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
property = Animator.camelize(property);
|
||||||
|
if(el.currentStyle){
|
||||||
|
style = el.currentStyle[property];
|
||||||
|
}
|
||||||
|
return style || el.style[property]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSSStyleSubject.ruleRe = /^\s*([a-zA-Z\-]+)\s*:\s*(\S(.+\S)?)\s*$/;
|
||||||
|
CSSStyleSubject.numericalRe = /^-?\d+(?:\.\d+)?(%|[a-zA-Z]{2})?$/;
|
||||||
|
CSSStyleSubject.discreteRe = /^\w+$/;
|
||||||
|
|
||||||
|
// required because the style object of elements isn't enumerable in Safari
|
||||||
|
/*
|
||||||
|
CSSStyleSubject.cssProperties = ['background-color','border','border-color','border-spacing',
|
||||||
|
'border-style','border-top','border-right','border-bottom','border-left','border-top-color',
|
||||||
|
'border-right-color','border-bottom-color','border-left-color','border-top-width','border-right-width',
|
||||||
|
'border-bottom-width','border-left-width','border-width','bottom','color','font-size','font-size-adjust',
|
||||||
|
'font-stretch','font-style','height','left','letter-spacing','line-height','margin','margin-top',
|
||||||
|
'margin-right','margin-bottom','margin-left','marker-offset','max-height','max-width','min-height',
|
||||||
|
'min-width','orphans','outline','outline-color','outline-style','outline-width','overflow','padding',
|
||||||
|
'padding-top','padding-right','padding-bottom','padding-left','quotes','right','size','text-indent',
|
||||||
|
'top','width','word-spacing','z-index','opacity','outline-offset'];*/
|
||||||
|
|
||||||
|
|
||||||
|
CSSStyleSubject.cssProperties = ['azimuth','background','background-attachment','background-color','background-image','background-position','background-repeat','border-collapse','border-color','border-spacing','border-style','border-top','border-top-color','border-right-color','border-bottom-color','border-left-color','border-top-style','border-right-style','border-bottom-style','border-left-style','border-top-width','border-right-width','border-bottom-width','border-left-width','border-width','bottom','clear','clip','color','content','cursor','direction','display','elevation','empty-cells','css-float','font','font-family','font-size','font-size-adjust','font-stretch','font-style','font-variant','font-weight','height','left','letter-spacing','line-height','list-style','list-style-image','list-style-position','list-style-type','margin','margin-top','margin-right','margin-bottom','margin-left','max-height','max-width','min-height','min-width','orphans','outline','outline-color','outline-style','outline-width','overflow','padding','padding-top','padding-right','padding-bottom','padding-left','pause','position','right','size','table-layout','text-align','text-decoration','text-indent','text-shadow','text-transform','top','vertical-align','visibility','white-space','width','word-spacing','z-index','opacity','outline-offset','overflow-x','overflow-y'];
|
||||||
|
|
||||||
|
|
||||||
|
// chains several Animator objects together
|
||||||
|
function AnimatorChain(animators, options) {
|
||||||
|
this.animators = animators;
|
||||||
|
this.setOptions(options);
|
||||||
|
for (var i=0; i<this.animators.length; i++) {
|
||||||
|
this.listenTo(this.animators[i]);
|
||||||
|
}
|
||||||
|
this.forwards = false;
|
||||||
|
this.current = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatorChain.prototype = {
|
||||||
|
// apply defaults
|
||||||
|
setOptions: function(options) {
|
||||||
|
this.options = Animator.applyDefaults({
|
||||||
|
// by default, each call to AnimatorChain.play() calls jumpTo(0) of each animator
|
||||||
|
// before playing, which can cause flickering if you have multiple animators all
|
||||||
|
// targeting the same element. Set this to false to avoid this.
|
||||||
|
resetOnPlay: true
|
||||||
|
}, options);
|
||||||
|
},
|
||||||
|
// play each animator in turn
|
||||||
|
play: function() {
|
||||||
|
this.forwards = true;
|
||||||
|
this.current = -1;
|
||||||
|
if (this.options.resetOnPlay) {
|
||||||
|
for (var i=0; i<this.animators.length; i++) {
|
||||||
|
this.animators[i].jumpTo(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.advance();
|
||||||
|
},
|
||||||
|
// play all animators backwards
|
||||||
|
reverse: function() {
|
||||||
|
this.forwards = false;
|
||||||
|
this.current = this.animators.length;
|
||||||
|
if (this.options.resetOnPlay) {
|
||||||
|
for (var i=0; i<this.animators.length; i++) {
|
||||||
|
this.animators[i].jumpTo(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.advance();
|
||||||
|
},
|
||||||
|
// if we have just play()'d, then call reverse(), and vice versa
|
||||||
|
toggle: function() {
|
||||||
|
if (this.forwards) {
|
||||||
|
this.seekTo(0);
|
||||||
|
} else {
|
||||||
|
this.seekTo(1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// internal: install an event listener on an animator's onComplete option
|
||||||
|
// to trigger the next animator
|
||||||
|
listenTo: function(animator) {
|
||||||
|
var oldOnComplete = animator.options.onComplete;
|
||||||
|
var _this = this;
|
||||||
|
animator.options.onComplete = function() {
|
||||||
|
if (oldOnComplete) oldOnComplete.call(animator);
|
||||||
|
_this.advance();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// play the next animator
|
||||||
|
advance: function() {
|
||||||
|
if (this.forwards) {
|
||||||
|
if (this.animators[this.current + 1] == null) return;
|
||||||
|
this.current++;
|
||||||
|
this.animators[this.current].play();
|
||||||
|
} else {
|
||||||
|
if (this.animators[this.current - 1] == null) return;
|
||||||
|
this.current--;
|
||||||
|
this.animators[this.current].reverse();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// this function is provided for drop-in compatibility with Animator objects,
|
||||||
|
// but only accepts 0 and 1 as target values
|
||||||
|
seekTo: function(target) {
|
||||||
|
if (target <= 0) {
|
||||||
|
this.forwards = false;
|
||||||
|
this.animators[this.current].seekTo(0);
|
||||||
|
} else {
|
||||||
|
this.forwards = true;
|
||||||
|
this.animators[this.current].seekTo(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// an Accordion is a class that creates and controls a number of Animators. An array of elements is passed in,
|
||||||
|
// and for each element an Animator and a activator button is created. When an Animator's activator button is
|
||||||
|
// clicked, the Animator and all before it seek to 0, and all Animators after it seek to 1. This can be used to
|
||||||
|
// create the classic Accordion effect, hence the name.
|
||||||
|
// see setOptions for arguments
|
||||||
|
function Accordion(options) {
|
||||||
|
this.setOptions(options);
|
||||||
|
var selected = this.options.initialSection, current;
|
||||||
|
if (this.options.rememberance) {
|
||||||
|
current = document.location.hash.substring(1);
|
||||||
|
}
|
||||||
|
this.rememberanceTexts = [];
|
||||||
|
this.ans = [];
|
||||||
|
var _this = this;
|
||||||
|
for (var i=0; i<this.options.sections.length; i++) {
|
||||||
|
var el = this.options.sections[i];
|
||||||
|
var an = new Animator(this.options.animatorOptions);
|
||||||
|
var from = this.options.from + (this.options.shift * i);
|
||||||
|
var to = this.options.to + (this.options.shift * i);
|
||||||
|
an.addSubject(new NumericalStyleSubject(el, this.options.property, from, to, this.options.units));
|
||||||
|
an.jumpTo(0);
|
||||||
|
var activator = this.options.getActivator(el);
|
||||||
|
activator.index = i;
|
||||||
|
activator.onclick = function(){_this.show(this.index)};
|
||||||
|
this.ans[this.ans.length] = an;
|
||||||
|
this.rememberanceTexts[i] = activator.innerHTML.replace(/\s/g, "");
|
||||||
|
if (this.rememberanceTexts[i] === current) {
|
||||||
|
selected = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.show(selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
Accordion.prototype = {
|
||||||
|
// apply defaults
|
||||||
|
setOptions: function(options) {
|
||||||
|
this.options = Object.extend({
|
||||||
|
// REQUIRED: an array of elements to use as the accordion sections
|
||||||
|
sections: null,
|
||||||
|
// a function that locates an activator button element given a section element.
|
||||||
|
// by default it takes a button id from the section's "activator" attibute
|
||||||
|
getActivator: function(el) {return document.getElementById(el.getAttribute("activator"))},
|
||||||
|
// shifts each animator's range, for example with options {from:0,to:100,shift:20}
|
||||||
|
// the animators' ranges will be 0-100, 20-120, 40-140 etc.
|
||||||
|
shift: 0,
|
||||||
|
// the first page to show
|
||||||
|
initialSection: 0,
|
||||||
|
// if set to true, document.location.hash will be used to preserve the open section across page reloads
|
||||||
|
rememberance: true,
|
||||||
|
// constructor arguments to the Animator objects
|
||||||
|
animatorOptions: {}
|
||||||
|
}, options || {});
|
||||||
|
},
|
||||||
|
show: function(section) {
|
||||||
|
for (var i=0; i<this.ans.length; i++) {
|
||||||
|
this.ans[i].seekTo(i > section ? 1 : 0);
|
||||||
|
}
|
||||||
|
if (this.options.rememberance) {
|
||||||
|
document.location.hash = this.rememberanceTexts[section];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 8.8 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 117 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 117 KiB |
|
@ -0,0 +1,127 @@
|
||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<metadata>
|
||||||
|
This is a custom SVG webfont generated by Font Squirrel.
|
||||||
|
Copyright : Generated in 2010 by FontLab Studio Copyright info pending
|
||||||
|
</metadata>
|
||||||
|
<defs>
|
||||||
|
<font id="ChunkFiveRegular" horiz-adv-x="696" >
|
||||||
|
<font-face units-per-em="2048" ascent="1536" descent="-512" />
|
||||||
|
<missing-glyph horiz-adv-x="500" />
|
||||||
|
<glyph unicode="!" horiz-adv-x="630" d="M57 209q0 84 64.5 150.5t169.5 66.5q106 0 175 -63.5t69 -153.5q0 -88 -68 -149.5t-176 -61.5q-98 0 -166 64.5t-68 146.5zM66 1042v390h489v-390l-109 -516h-270z" />
|
||||||
|
<glyph unicode=""" horiz-adv-x="1032" d="M72 1436h393l-62 -613h-256zM567 1436h394l-74 -613h-256z" />
|
||||||
|
<glyph unicode="#" horiz-adv-x="1536" d="M31 375v278h299l59 234h-246v278h316l96 375h270l-96 -375h275l96 375h270l-96 -375h231v-278h-301l-59 -234h248v-278h-320l-94 -377l-270 4l94 373h-275l-94 -377l-270 4l94 373h-227zM600 653h274l60 234h-275z" />
|
||||||
|
<glyph unicode="$" horiz-adv-x="1234" d="M31 35v493h321q0 -57 27 -98t70 -60.5t78.5 -27.5t72.5 -10q150 0 150 100q0 41 -69 74t-166 66.5t-195.5 81.5t-167 141.5t-68.5 220.5q0 188 113.5 289.5t261.5 111.5v172h289v-213q78 -37 114 -100l17 115h299v-480h-316q0 104 -63.5 166t-163.5 62q-43 0 -82 -28 t-39 -77q0 -47 51 -84t128 -62.5t166 -64.5t166 -84t128 -128t51 -189.5t-41 -186t-109.5 -123.5t-144 -64.5t-161.5 -22.5v-211h-289v268q-55 31 -107 76l-22 -123h-299z" />
|
||||||
|
<glyph unicode="%" horiz-adv-x="1906" d="M31 1051q0 180 125 298.5t288 118.5q199 0 310.5 -114.5t111.5 -309.5q0 -184 -110.5 -300.5t-302.5 -116.5q-186 0 -304 115.5t-118 308.5zM336 1051q0 -104 37 -170t80 -66q47 0 76.5 62.5t29.5 166.5q0 100 -32.5 166t-80.5 66q-41 2 -75.5 -60.5t-34.5 -164.5zM387 0 l885 1432h233l-887 -1432h-231zM1040 424q0 180 125 299t289 119q199 0 310.5 -115t111.5 -309q0 -184 -110.5 -301t-303.5 -117q-186 0 -304 115.5t-118 308.5zM1346 424q0 -104 36.5 -170t79.5 -66q47 0 77 62.5t30 167.5q0 100 -33 165.5t-80 65.5q-41 2 -75.5 -60.5 t-34.5 -164.5z" />
|
||||||
|
<glyph unicode="&" horiz-adv-x="1579" d="M20 420q0 264 302 418q-63 41 -106.5 115.5t-43.5 154.5q0 135 125 241.5t313 106.5q219 0 333 -106.5t114 -241.5q0 -111 -67.5 -184.5t-166.5 -114.5l191 -191q59 111 106 273h439v-258h-201q-47 -135 -117 -242l127 -125h119v-266h-305l-133 131q-80 -74 -210 -116 t-276 -42q-250 0 -396.5 126t-146.5 321zM403 432q0 -70 51.5 -113t114.5 -43q145 0 242 86l-260 256h-8q-51 -33 -95.5 -84t-44.5 -102zM506 1114q0 -94 123 -147q6 -4 29.5 14t46 52t22.5 69q0 51 -28.5 88t-90.5 37q-43 0 -72.5 -35t-29.5 -78z" />
|
||||||
|
<glyph unicode="'" horiz-adv-x="559" d="M74 1436h405l-73 -613h-256z" />
|
||||||
|
<glyph unicode="(" horiz-adv-x="794" d="M51 639q0 170 50.5 341t128 303t154.5 227.5t148 158.5l211 -217q-59 -74 -94 -122t-96 -156.5t-93 -243.5t-32 -291q0 -162 29.5 -301t85 -245.5t97.5 -168t103 -133.5l-211 -219q-193 174 -337 459.5t-144 607.5z" />
|
||||||
|
<glyph unicode=")" horiz-adv-x="794" d="M51 -211q61 72 103.5 133.5t97.5 168t85 245.5t30 301q0 156 -32 291t-93.5 243.5t-96 156.5t-94.5 122l211 217q72 -63 148.5 -158.5t154.5 -227.5t128 -303t50 -341q0 -322 -144 -607.5t-337 -459.5z" />
|
||||||
|
<glyph unicode="*" horiz-adv-x="845" d="M10 1085l84 201l234 -108l-27 254h252l-33 -261l232 115l84 -201l-248 -81l184 -197l-186 -143l-162 227l-170 -234l-180 152l178 192z" />
|
||||||
|
<glyph unicode="+" horiz-adv-x="1120" d="M51 625v266h377v377h266v-377h375v-266h-375v-375h-266v375h-377z" />
|
||||||
|
<glyph unicode="," horiz-adv-x="557" d="M-12 -264q115 145 162 294.5t32 370.5l373 -98q6 -195 -82 -376t-250 -324z" />
|
||||||
|
<glyph unicode="-" d="M51 352v273h594v-273h-594z" />
|
||||||
|
<glyph unicode="." horiz-adv-x="528" d="M31 213q0 86 63.5 159.5t168 73.5t170 -73.5t65.5 -159.5q0 -96 -62.5 -158.5t-173.5 -62.5q-98 0 -164.5 67.5t-66.5 153.5z" />
|
||||||
|
<glyph unicode="/" horiz-adv-x="1073" d="M10 -160l762 1700h291l-762 -1704z" />
|
||||||
|
<glyph unicode="0" horiz-adv-x="1226" d="M31 723q0 326 160.5 530.5t416.5 204.5q293 0 440.5 -199.5t147.5 -549.5q0 -344 -150.5 -539t-427.5 -195q-266 0 -426.5 190.5t-160.5 557.5zM436 723q0 -186 57.5 -308t124.5 -122q72 0 119 115.5t47 300.5q0 182 -51 300.5t-127 118.5q-61 2 -115.5 -113.5 t-54.5 -291.5z" />
|
||||||
|
<glyph unicode="1" horiz-adv-x="1015" d="M51 1163l42 21l44 21l39 21q29 15 43 26l41 31q27 19 47 40l48 48q28 28 55 61h364v-1160h191v-272h-820v272h205v760l-205 -96z" />
|
||||||
|
<glyph unicode="2" horiz-adv-x="1208" d="M51 0v297q82 135 140.5 201.5t158.5 146.5q47 43 150.5 111.5t158 121t54.5 109.5q0 135 -172 135q-51 0 -103.5 -29.5t-77 -53t-71.5 -72.5l-221 233q219 254 532 254q209 0 348 -123t139 -325q0 -164 -70.5 -251t-256.5 -208q-86 -55 -180.5 -136t-126.5 -139h360v164 h344v-436h-1106z" />
|
||||||
|
<glyph unicode="3" horiz-adv-x="1105" d="M31 205l209 217q133 -133 270 -133q86 0 135 41t49 116q0 150 -170 150h-153v244h149q76 0 125 36.5t49 104.5q0 78 -54 120t-126 42q-123 0 -240 -123l-198 240q66 72 188.5 133t249.5 61q248 0 385 -117.5t137 -316.5q0 -143 -151 -260q190 -137 190 -336 q0 -213 -170 -332t-397 -119q-141 0 -278.5 70t-198.5 162z" />
|
||||||
|
<glyph unicode="4" horiz-adv-x="1196" d="M20 403v293l590 736h424v-807h109v-222h-109v-133h111v-270h-664v270h129v133h-590zM307 625h303v379z" />
|
||||||
|
<glyph unicode="5" horiz-adv-x="1181" d="M31 221l223 232q147 -152 287 -152q102 0 163.5 57.5t61.5 147.5q0 82 -60.5 140.5t-148.5 58.5q-102 0 -192 -95l-263 117l125 705h811v-306h-551l-34 -198q76 49 221 49q193 0 335 -130t142 -355q0 -125 -53.5 -225.5t-141.5 -163t-195.5 -96.5t-221.5 -34 q-150 0 -296 75t-212 173z" />
|
||||||
|
<glyph unicode="6" horiz-adv-x="1189" d="M33 623q-2 96 8 191t47 213t99.5 207t178 152.5t269.5 67.5q109 4 253 -42t230 -120l-139 -266q-178 104 -299 104q-111 -2 -181.5 -80.5t-86.5 -197.5q41 41 115.5 71.5t152.5 32.5q201 8 340 -121.5t139 -334.5q0 -213 -143.5 -361.5t-386.5 -156.5q-256 -8 -422 165 t-174 476zM416 545q0 -88 50 -165t140 -77q78 0 133.5 51.5t53.5 124.5q-2 72 -42 128.5t-124 54.5q-121 -6 -211 -117z" />
|
||||||
|
<glyph unicode="7" horiz-adv-x="1159" d="M31 1026v406h1108v-273l-551 -1159h-443l549 1159h-336v-133h-327z" />
|
||||||
|
<glyph unicode="8" horiz-adv-x="1144" d="M31 420q0 102 61.5 206.5t159.5 153.5q-74 45 -114 120t-40 153q0 176 131 289.5t357 113.5q231 0 360 -113.5t129 -289.5q0 -96 -49 -170t-123 -109q100 -49 155.5 -147.5t55.5 -206.5q0 -193 -148.5 -320t-392.5 -127q-250 0 -396 126t-146 321zM385 432 q0 -72 56.5 -120t133.5 -48q80 0 133.5 44t55.5 124q0 94 -81 136t-179 46q-49 -29 -84 -79t-35 -103zM434 1069q0 -51 39 -84t79 -41t85 -10q98 47 98 135q0 55 -46 92t-107 37q-59 0 -103.5 -39t-44.5 -90z" />
|
||||||
|
<glyph unicode="9" horiz-adv-x="1202" d="M31 936q0 213 143 361.5t387 156.5q258 8 429 -166t179 -475q2 -106 -8 -205.5t-50 -215.5t-104.5 -202t-181 -145t-270.5 -63q-109 -4 -253 42t-230 119l139 267q178 -104 299 -105q117 4 184.5 76t65.5 203q-98 -98 -250 -105q-201 -8 -340 122t-139 335zM397 956 q2 -72 42 -128t124 -54q102 4 193 117q0 94 -42 168t-130 74q-78 0 -133.5 -51.5t-53.5 -125.5z" />
|
||||||
|
<glyph unicode=":" horiz-adv-x="520" d="M31 201q0 86 62.5 157.5t164.5 71.5q104 0 167.5 -72.5t63.5 -156.5q0 -92 -64.5 -154.5t-166.5 -62.5q-96 0 -161.5 66.5t-65.5 150.5zM31 823q0 86 62.5 158t164.5 72q104 0 167.5 -73t63.5 -157q0 -94 -62 -155.5t-169 -61.5q-92 0 -159.5 67.5t-67.5 149.5z" />
|
||||||
|
<glyph unicode=";" horiz-adv-x="618" d="M10 -264l236 -133q162 143 250 324.5t82 375.5l-373 98q14 -221 -33 -370.5t-162 -294.5zM121 788q0 86 63.5 160t168 74t170 -74t65.5 -160q0 -94 -63.5 -157.5t-172.5 -63.5q-94 0 -162.5 68.5t-68.5 152.5z" />
|
||||||
|
<glyph unicode="<" horiz-adv-x="1124" d="M72 694v256l880 363l101 -250l-627 -240l627 -241l-101 -250z" />
|
||||||
|
<glyph unicode="=" horiz-adv-x="946" d="M51 352v273h844v-273h-844zM51 805v272h844v-272h-844z" />
|
||||||
|
<glyph unicode=">" horiz-adv-x="1124" d="M72 584l626 239l-626 242l100 250l881 -363v-256l-881 -362z" />
|
||||||
|
<glyph unicode="?" horiz-adv-x="1064" d="M4 1200q227 264 533 264q213 0 350 -109.5t137 -310.5q0 -74 -34 -136t-82 -104t-95 -77t-81 -69.5t-34 -67.5v-113h-379l-2 164q0 63 51.5 126.5t112 105.5t111.5 90.5t51 85.5q0 96 -151 96q-61 0 -134 -49t-133 -119zM264 209q0 84 64.5 150.5t169.5 66.5 q106 0 174.5 -63.5t68.5 -153.5q0 -88 -67.5 -149.5t-175.5 -61.5q-98 0 -166 64.5t-68 146.5z" />
|
||||||
|
<glyph unicode="@" horiz-adv-x="1595" d="M10 465q0 106 28 218t89 221.5t148 195.5t217.5 139t283.5 53q369 0 589 -207.5t220 -521.5q0 -57 -10 -116.5t-37 -126t-66.5 -116.5t-108.5 -83t-155 -33q-129 16 -184 68q-135 -98 -270 -99q-143 0 -257 119t-114 299q0 100 45 199.5t143.5 174.5t225.5 75 q113 0 200 -107l13 82l202 -27l-82 -583q2 0 3 -2q41 -25 75 -25q109 0 158 96.5t49 204.5q0 238 -174 396.5t-465 158.5q-147 0 -266 -63.5t-187.5 -163.5t-104.5 -210t-36 -216q0 -254 183.5 -433t449.5 -179q270 0 455 133l20 16l99 -141q-8 -8 -24.5 -19.5t-72 -43 t-118 -55.5t-159.5 -43t-200 -19q-326 0 -565.5 221t-239.5 563zM608 475q0 -92 44 -152.5t102 -60.5q88 0 172 49l39 267q-68 141 -168 141q-86 0 -137.5 -78t-51.5 -166z" />
|
||||||
|
<glyph unicode="A" horiz-adv-x="1685" d="M31 0v268h139l276 899h-84v265h787l362 -1164h144v-268h-821v268h194l-43 140h-420l-43 -140h160v-268h-651zM641 653h268l-135 443z" />
|
||||||
|
<glyph unicode="B" horiz-adv-x="1406" d="M51 0v266h119v901h-119v265h764q502 0 502 -351q0 -131 -44 -201.5t-157 -115.5q121 -33 195.5 -120t74.5 -228q0 -217 -131 -316.5t-426 -99.5h-778zM594 266h164q68 0 117 48t49 128t-45 130.5t-127 50.5h-158v-357zM594 854h125q78 0 108.5 40t30.5 118 q0 70 -38 109.5t-97 39.5h-129v-307z" />
|
||||||
|
<glyph unicode="C" horiz-adv-x="1404" d="M31 702q0 168 59.5 314.5t151.5 240t200.5 146.5t210.5 53q211 0 316 -139l47 115h321v-582h-366q-4 109 -59.5 183.5t-157.5 74.5q-109 0 -176.5 -117t-67.5 -289q0 -162 80 -273.5t219 -111.5q31 0 62.5 8.5t58 20.5t53.5 29.5t46.5 34t40 36t30.5 31.5l22 27l13 14 l239 -262q-262 -289 -620 -289q-328 0 -525.5 197.5t-197.5 537.5z" />
|
||||||
|
<glyph unicode="D" horiz-adv-x="1474" d="M51 0v272h127v889h-127v271h625q362 0 570 -197t208 -500q0 -350 -205 -542.5t-581 -192.5h-617zM598 272h78q156 2 231.5 130t75.5 333q0 180 -77 303t-230 123h-78v-889z" />
|
||||||
|
<glyph unicode="E" horiz-adv-x="1337" d="M51 0v272h129v889h-129v271h1235v-453h-354v182h-328v-282h389v-273h-389v-334h328v191h354v-463h-1235z" />
|
||||||
|
<glyph unicode="F" horiz-adv-x="1306" d="M51 0v272h127v889h-127v271h1225v-453h-363v182h-309v-356h389v-273h-389v-260h209v-272h-762z" />
|
||||||
|
<glyph unicode="G" horiz-adv-x="1589" d="M31 702q0 324 189.5 539t438.5 215q70 0 130.5 -11t98.5 -25.5t70.5 -37t48 -38t32 -36t20.5 -24.5l43 148h305v-605h-367q-4 121 -71.5 190.5t-161.5 69.5q-121 0 -201 -113.5t-80 -271.5q0 -162 76 -269t205 -107q139 0 197 100v86h-125v219h680v-219h-82v-512h-410 l-63 129q-37 -61 -127.5 -104t-202.5 -43q-274 0 -458.5 197t-184.5 523z" />
|
||||||
|
<glyph unicode="H" horiz-adv-x="1572" d="M51 0v270h113v891h-113v271h664v-271h-127v-309h389v309h-121v271h666v-271h-119v-891h119v-270h-666v270h121v310h-389v-310h127v-270h-664z" />
|
||||||
|
<glyph unicode="I" horiz-adv-x="782" d="M51 0v272h129v889h-129v271h680v-271h-127v-889h127v-272h-680z" />
|
||||||
|
<glyph unicode="J" horiz-adv-x="948" d="M41 -125q41 -18 92 -18q170 0 170 295v1011h-176v269h770v-269h-170v-1011q0 -283 -135 -426.5t-442 -143.5q-51 0 -107 23z" />
|
||||||
|
<glyph unicode="K" horiz-adv-x="1669" d="M51 0v266h111v901h-111v265h645v-265h-110v-333l381 333h-148v265h682v-265h-119l-297 -256l414 -645h119v-266h-799v266h139l-221 348l-151 -129v-219h110v-266h-645z" />
|
||||||
|
<glyph unicode="L" horiz-adv-x="1249" d="M51 0v272h113v889h-113v271h647v-271h-108v-889h264v260h344v-532h-1147z" />
|
||||||
|
<glyph unicode="M" horiz-adv-x="2064" d="M51 0v264h111v903h-109v265h776l207 -766l197 766h780v-265h-112v-901h112v-266h-647v266h117l-2 684v121h-8q-35 -190 -60 -274l-215 -797h-428l-229 817q-35 119 -43 254h-9v-807h117v-264h-555z" />
|
||||||
|
<glyph unicode="N" horiz-adv-x="1671" d="M51 0v264h121v903h-119v265h588l504 -752l-2 487h-139v265h616v-265h-135v-1167h-441l-522 780v-516h158v-264h-629z" />
|
||||||
|
<glyph unicode="O" horiz-adv-x="1515" d="M31 723q0 332 200.5 539.5t518.5 207.5q367 0 551 -202.5t184 -558.5q0 -350 -188.5 -548t-532.5 -198q-334 0 -533.5 193.5t-199.5 566.5zM537 723q0 -199 63.5 -318.5t163.5 -119.5q96 0 152.5 115.5t56.5 308.5q0 199 -56.5 322.5t-168.5 123.5h-4q-92 0 -149 -120 q-58 -122 -58 -312z" />
|
||||||
|
<glyph unicode="P" horiz-adv-x="1310" d="M51 0v270h115v893h-115v269h664q172 0 287.5 -34t174 -99.5t81 -137t22.5 -168.5q0 -195 -153.5 -300t-385.5 -105h-155v-318h125v-270h-660zM586 809h92q90 0 145.5 45t55.5 125q0 90 -50.5 138t-140.5 48h-102v-356z" />
|
||||||
|
<glyph unicode="Q" horiz-adv-x="1546" d="M31 725q0 315 190.5 514t497.5 199q350 0 525 -193.5t175 -533.5q0 -326 -170 -512q35 -133 90 -133q41 0 41 92v59h136v-104q0 -143 -80 -235.5t-228 -92.5q-119 0 -199.5 64.5t-117.5 162.5q-74 -12 -160 -12q-319 0 -509.5 186.5t-190.5 538.5zM481 725q0 -66 8 -113 q94 98 242 99q119 0 230 -80q4 49 4 80q0 182 -69 305t-179 123h-3q-92 0 -162 -118q-71 -120 -71 -296zM594 375q61 -68 137 -68q57 0 109 45q-12 86 -36 129t-73 43q-84 1 -137 -149z" />
|
||||||
|
<glyph unicode="R" horiz-adv-x="1509" d="M51 0v270h115v893h-115v269h666q172 0 287.5 -32t175 -93.5t82 -131t22.5 -165.5q0 -117 -83 -198t-214 -99q109 -16 188.5 -99.5t79.5 -191.5q0 -139 50 -139q47 0 47 65v68h137v-113q0 -143 -70.5 -235.5t-228.5 -92.5q-199 0 -298 99.5t-99 281.5q0 143 -36 187.5 t-169 44.5v-318h125v-270h-662zM588 817h92q90 0 143.5 43t53.5 123q0 182 -187 182h-102v-348z" />
|
||||||
|
<glyph unicode="S" horiz-adv-x="1454" d="M51 0v516h381q0 -61 26.5 -103t71.5 -62.5t82 -29t78 -10.5q174 0 174 103q0 37 -58 65.5t-145.5 48t-189.5 57.5t-189 87t-145.5 141t-58.5 215q0 109 47 196t122 139t156.5 78.5t161.5 26.5q317 0 428 -208l21 172h352v-514h-371q0 111 -74.5 174t-187.5 63 q-51 0 -96 -29.5t-45 -78.5q0 -57 84 -100.5t202.5 -81.5t237.5 -87t203 -145t84 -230q0 -115 -49 -201.5t-131 -136t-174.5 -73t-188.5 -23.5q-268 0 -428 189l-22 -158h-359z" />
|
||||||
|
<glyph unicode="T" horiz-adv-x="1435" d="M31 899v533h1374v-533h-301v262h-172v-889h170v-272h-762v272h168v889h-176v-262h-301z" />
|
||||||
|
<glyph unicode="U" horiz-adv-x="1509" d="M31 1165v267h651v-265h-111v-442q0 -233 49.5 -316t155.5 -83q70 0 111 25.5t68.5 116.5t27.5 259v434h-111v271h607v-265h-111v-497q0 -705 -588 -705q-635 18 -635 694v506h-114z" />
|
||||||
|
<glyph unicode="V" horiz-adv-x="1583" d="M-20 1165v267h755l-2 -267h-110l174 -458q59 -180 63 -248h10q6 92 74 260l186 446h-106l-2 267h582v-267h-101l-491 -1165h-377l-543 1165h-112z" />
|
||||||
|
<glyph unicode="W" horiz-adv-x="2078" d="M-20 1165v267h675v-267h-118l53 -299q29 -123 65 -403h11q4 47 100 508l102 461h426l129 -566q39 -182 62 -403h10q16 178 61 391l70 311h-113v267h586v-267h-112l-306 -1165h-485l-123 487q-27 98 -51 254h-8q-14 -102 -49 -249l-125 -492h-475l-271 1165h-114z" />
|
||||||
|
<glyph unicode="X" horiz-adv-x="1710" d="M51 0v264h178l301 391l-370 510h-107v267h811v-267h-119l201 -272l209 272h-180v267h680v-267h-174l-310 -395l369 -504h119v-266h-817v266h116l-155 209l-43 57l-211 -268h182v-264h-680z" />
|
||||||
|
<glyph unicode="Y" horiz-adv-x="1370" d="M-20 1169v263h700v-263h-107l119 -217q6 -16 33 -81.5t31 -84.5h8q4 18 76 177l112 206h-112v263h551v-263h-111l-379 -665v-238h115v-266h-656v266h117v242l-397 661h-100z" />
|
||||||
|
<glyph unicode="Z" horiz-adv-x="1462" d="M51 0v266l746 895l-387 -2l2 -266h-349v539h1344l4 -273l-749 -889h378l2 262h363v-532h-1354z" />
|
||||||
|
<glyph unicode="[" horiz-adv-x="1474" d="M59 0v270h115v893h-115v271h664q170 0 286.5 -39t175 -108.5t81 -145.5t22.5 -174q0 -215 -221 -338l229 -363h119v-266h-393l-340 549h-88v-279h125v-270h-660zM594 809h92q90 0 145.5 45t55.5 125q0 90 -50.5 138t-140.5 48h-102v-356z" />
|
||||||
|
<glyph unicode="\" horiz-adv-x="1073" d="M10 1540h291l762 -1700l-291 -4z" />
|
||||||
|
<glyph unicode="]" horiz-adv-x="1325" d="M61 0v266h84v1002h-84v268h474v-926l237 142h-147v272h573v-272h-158l-129 -76l285 -408h84v-268h-332l-344 489l-72 -49v-172h146v-268h-617z" />
|
||||||
|
<glyph unicode="^" horiz-adv-x="1222" d="M20 621l445 813h297l440 -813h-364l-224 458l-229 -458h-365z" />
|
||||||
|
<glyph unicode="_" horiz-adv-x="1431" d="M51 -2v170h1329v-170h-1329z" />
|
||||||
|
<glyph unicode="a" horiz-adv-x="1228" d="M31 303q0 170 124 273.5t302 103.5q55 0 103 -16.5t69.5 -31t29.5 -24.5v72q0 115 -194 115q-135 0 -305 -95l-86 238q242 145 446 145q100 0 191.5 -20.5t176.5 -65.5t136 -132t51 -203v-400h123v-262h-438l-49 92q-51 -70 -129 -100.5t-148 -30.5q-162 0 -282.5 88 t-120.5 254zM420 324q0 -43 30.5 -70t77.5 -27q43 0 79 20.5t52 47.5v78q-35 59 -120 59q-119 1 -119 -108z" />
|
||||||
|
<glyph unicode="b" horiz-adv-x="1343" d="M63 0v266h87v1002h-87v268h496v-592q33 39 113 67.5t155 28.5q223 0 350 -158q122 -154 122 -364q0 -7 -1 -14q-4 -240 -131 -383.5t-342 -143.5q-74 0 -128 14.5t-80.5 31t-61.5 47.5l-31 -70h-461zM555 489q0 -102 44 -173.5t103 -71.5q66 0 106 69.5t40 186.5 q0 98 -41 175t-107 77q-63 0 -107 -73q-39 -64 -39 -162q0 -14 1 -28z" />
|
||||||
|
<glyph unicode="c" horiz-adv-x="1087" d="M2 518q0 256 145.5 390t358.5 134q158 0 256 -116l35 98h241v-463h-301q-4 88 -34.5 151.5t-94.5 63.5q-86 0 -133 -76.5t-47 -185.5q0 -102 57.5 -171t153.5 -71h5q136 0 243 117l180 -209q-80 -88 -213 -148.5t-289 -60.5q-240 0 -401.5 143.5t-161.5 403.5z" />
|
||||||
|
<glyph unicode="d" horiz-adv-x="1298" d="M20 522q0 231 139.5 376.5t336.5 145.5q135 0 258 -77v303h-95v266h510v-1270h99v-266h-480l-34 76q-102 -94 -258 -94q-211 0 -343.5 159.5t-132.5 380.5zM461 522q0 -98 41 -175t106 -77q63 0 108 73q39 64 38 162v27q0 102 -44 174t-104 72q-66 0 -105.5 -69.5 t-39.5 -186.5z" />
|
||||||
|
<glyph unicode="e" horiz-adv-x="1110" d="M10 518q0 246 156 390.5t395 144.5q180 0 312.5 -83t177.5 -214q23 -66 27 -156q1 -14 1 -27q0 -78 -24 -163h-645q6 -31 14 -51.5t29.5 -52.5t64.5 -48t103 -16q168 0 286 98l172 -199q-207 -178 -528 -178q-215 0 -378 141.5t-163 413.5zM416 612h309q-2 74 -32.5 119 t-119.5 45q-82 0 -117.5 -53.5t-39.5 -110.5z" />
|
||||||
|
<glyph unicode="f" horiz-adv-x="790" d="M51 758v266h84v174q0 43 6 84t31 97.5t66 96.5t119.5 68.5t183.5 28.5q80 0 170 -15.5t131 -35.5l-123 -236q-45 20 -113 21q-66 0 -65 -109v-174h186v-266h-186v-490h123v-268h-611v268h82v490h-84z" />
|
||||||
|
<glyph unicode="g" horiz-adv-x="1310" d="M20 518q0 244 133.5 385t381.5 141q63 0 123.5 -25.5t93.5 -57.5l41 63h487v-268h-123v-613q0 -262 -161.5 -411.5t-477.5 -151.5q-152 2 -272.5 56.5t-196.5 123.5l109 228q49 -43 151.5 -87t204.5 -44q125 0 181.5 57t56.5 135v70q-88 -113 -240 -113 q-246 0 -369 148.5t-123 363.5zM457 522q0 -98 41 -175t106 -77q63 0 108 73q39 64 38 162v27q0 102 -44 174t-104 72q-66 0 -105.5 -69.5t-39.5 -186.5z" />
|
||||||
|
<glyph unicode="h" horiz-adv-x="1353" d="M51 0v268h86v1002h-86v266h496v-639q25 41 124 102.5t197 61.5q113 0 189 -38t110.5 -108.5t47 -140t12.5 -164.5v-342h96v-268h-526v557q0 39 -2 61.5t-12.5 57.5t-37 53.5t-69.5 18.5q-129 0 -129 -191v-289h147v-268h-643z" />
|
||||||
|
<glyph unicode="i" horiz-adv-x="675" d="M51 0v268h86v490h-86v266h475v-756h99v-268h-574zM109 1323q0 78 60 143.5t160.5 65.5t163 -65.5t62.5 -143.5q0 -88 -60.5 -147.5t-164.5 -59.5q-92 0 -156.5 64.5t-64.5 142.5z" />
|
||||||
|
<glyph unicode="j" horiz-adv-x="737" d="M29 -154q68 0 114.5 24t69.5 51.5t35 77.5t13 74.5t1 69.5v615h-86v266h475v-881q0 -86 -12 -157.5t-51 -151.5t-104.5 -135t-181.5 -91t-273 -36v274zM233 1323q0 78 60.5 143.5t161 65.5t163 -65.5t62.5 -143.5q0 -88 -60.5 -147.5t-164.5 -59.5q-92 0 -157 64.5 t-65 142.5z" />
|
||||||
|
<glyph unicode="k" horiz-adv-x="1339" d="M78 0v266h84v1002h-84v268h473v-926l237 142h-147v270h573v-270h-157l-139 -88l276 -396h102v-268h-606v268h86l-155 221l-72 -49v-172h76v-268h-547z" />
|
||||||
|
<glyph unicode="l" horiz-adv-x="679" d="M51 0v268h88v1004h-86v264h475v-1268h121v-268h-598z" />
|
||||||
|
<glyph unicode="m" horiz-adv-x="1859" d="M51 0v268h86v484h-86v270h387l45 -121q125 150 256 150q72 0 128.5 -14.5t92 -42t51 -46t33.5 -45.5q131 147 302 148q119 0 198.5 -40t117.5 -115t52.5 -152.5t14.5 -184.5v-283h100v-276h-520v502q0 12 1 44t1 50t-2 46t-7.5 45.5t-13.5 34.5t-22.5 25.5t-34.5 8.5 q-61 0 -85 -38t-24 -112v-332h123v-274h-530v522q0 137 -14.5 185.5t-71.5 48.5q-92 0 -92 -123v-365h122v-268h-608z" />
|
||||||
|
<glyph unicode="n" horiz-adv-x="1325" d="M51 0v268h86v490h-86v266h436l48 -127q119 164 292 164q92 0 161 -26.5t108 -68.5t62.5 -104.5t31.5 -121t8 -130.5v-342h96v-268h-516v559v48q0 11 -5 47t-16.5 50.5t-35 30t-57.5 15.5q-129 0 -129 -191v-291h147v-268h-631z" />
|
||||||
|
<glyph unicode="o" horiz-adv-x="1175" d="M191 904q167 144 393 145q250 -4 407.5 -147.5t161.5 -393.5v-6q0 -243 -158 -385q-160 -143 -401 -144q-238 0 -406 143q-166 141 -165 394q-1 248 168 394zM442 514q0 -125 43 -201.5t109 -76.5q63 0 101 76.5t38 195.5t-40 195.5t-109 78.5q-59 0 -100.5 -77.5 t-41.5 -190.5z" />
|
||||||
|
<glyph unicode="p" horiz-adv-x="1306" d="M51 -150h86v902h-86v272h469l35 -72q119 88 248 88q229 0 356 -153.5t127 -382.5q0 -240 -132 -383.5t-335 -143.5q-172 0 -266 80v-207h111v-268h-613v268zM553 489q0 -102 44 -173.5t103 -71.5q66 0 106 69.5t40 186.5q0 98 -41 175t-107 77q-63 0 -107 -73 q-39 -64 -39 -162q0 -14 1 -28z" />
|
||||||
|
<glyph unicode="q" horiz-adv-x="1351" d="M51 518q0 256 137.5 391t352.5 135q88 0 155.5 -27.5t87.5 -53.5l39 61h477v-266h-100v-955h100v-274h-649v268h133v271q-104 -86 -262 -86q-201 0 -336 147t-135 389zM492 516q0 -102 44 -174t103 -72q66 0 105.5 70t39.5 186q0 98 -41 175t-106 77q-63 0 -108 -72 q-39 -64 -38 -162q0 -14 1 -28z" />
|
||||||
|
<glyph unicode="r" horiz-adv-x="847" d="M51 0v268h90v490h-88v266h385l62 -131q25 45 44 70.5t54 55.5t89 43t130 13v-368q-147 0 -218 -49.5t-71 -178.5v-211h103v-268h-580z" />
|
||||||
|
<glyph unicode="s" horiz-adv-x="1040" d="M31 0v369h274q0 -49 44 -83t89 -44.5t84 -10.5q90 0 90 70q0 18 -16 31.5t-48 24t-66 19.5l-84 22q-50 13 -87 26q-272 96 -272 328q0 143 115.5 220t244.5 77q102 0 187.5 -46.5t118.5 -113.5l16 135h252v-369h-266q0 63 -64.5 109.5t-144.5 46.5t-80 -74 q0 -16 12 -29.5t41 -26.5t51.5 -21.5t72.5 -24.5l75 -25q80 -27 120.5 -45t98 -56t84 -94.5t26.5 -131.5q0 -139 -112.5 -223.5t-268.5 -84.5q-104 0 -189 43t-124 107l-18 -125h-256z" />
|
||||||
|
<glyph unicode="t" horiz-adv-x="743" d="M31 758v266h110v188l377 121v-309h195v-266h-195v-365q0 -8 -1 -29.5t0 -34t2 -29.5t5 -27.5t11.5 -21.5t19.5 -16.5t29 -5.5q47 0 129 35v-262q-41 -16 -122 -27.5t-126 -11.5q-90 0 -150.5 21.5t-94.5 52.5t-51 94.5t-21.5 114.5t-6.5 147v365h-110z" />
|
||||||
|
<glyph unicode="u" horiz-adv-x="1292" d="M31 754v270h495v-494q0 -135 24.5 -196.5t86.5 -61.5q55 0 92 44t37 112v326h-135v270h530v-752h101v-272h-388l-55 129l-20 -23q-20 -25 -28 -31l-30 -29q-23 -22 -41 -30t-44.5 -21t-58.5 -18.5t-69 -5.5q-227 0 -319 119t-92 381v283h-86z" />
|
||||||
|
<glyph unicode="v" horiz-adv-x="1255" d="M0 764v260h623v-260h-103l94 -217q45 -133 54 -215h8q4 94 61 225l99 207h-109v260h528v-260h-106l-354 -764h-318l-381 764h-96z" />
|
||||||
|
<glyph unicode="w" horiz-adv-x="1785" d="M0 758v266h551v-266h-70l45 -150q41 -139 52 -295h4q20 268 84 482l65 229h379l78 -266q59 -188 88 -445h4q18 193 55 324l35 121h-84v266h500v-266h-84l-240 -758h-432l-141 463l-148 -463h-422l-231 758h-88z" />
|
||||||
|
<glyph unicode="x" horiz-adv-x="1329" d="M41 0v254h137l209 235l-254 279h-92v256h664v-256h-97l144 -156l153 156h-137v256h522v-256h-135l-217 -219l258 -295h96v-254h-653v254h96l-155 166l-148 -166h133v-254h-524z" />
|
||||||
|
<glyph unicode="y" horiz-adv-x="1187" d="M-18 762v262h630v-260h-96l133 -320l133 320h-94v260h520v-254h-98l-389 -946q-23 -49 -40 -80t-54 -76t-80 -70.5t-111.5 -44t-154.5 -18.5q-139 8 -248 103l153 241q68 -59 119 -69q9 -2 18 -2q34 0 62 26q35 33 51 84l29 86l-399 758h-84z" />
|
||||||
|
<glyph unicode="z" horiz-adv-x="1132" d="M51 0v268l494 492h-228v-146h-266v410h1014v-264l-487 -492h215v140h288v-408h-1030z" />
|
||||||
|
<glyph unicode="|" horiz-adv-x="681" d="M205 -418v1854h272v-1854h-272z" />
|
||||||
|
<glyph unicode="­" d="M51 352v273h594v-273h-594z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="833" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="1669" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="833" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="1669" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="555" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="415" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="276" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="276" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="206" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="333" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="92" />
|
||||||
|
<glyph unicode="‐" d="M51 352v273h594v-273h-594z" />
|
||||||
|
<glyph unicode="‑" d="M51 352v273h594v-273h-594z" />
|
||||||
|
<glyph unicode="‒" d="M51 352v273h594v-273h-594z" />
|
||||||
|
<glyph unicode="–" horiz-adv-x="915" d="M66 352v273h772v-273h-772z" />
|
||||||
|
<glyph unicode="—" horiz-adv-x="1292" d="M86 352v273h1104v-273h-1104z" />
|
||||||
|
<glyph unicode="’" horiz-adv-x="559" d="M74 1436h405l-73 -613h-256z" />
|
||||||
|
<glyph unicode="“" horiz-adv-x="1032" d="M72 1436h393l-62 -613h-256zM567 1436h394l-74 -613h-256z" />
|
||||||
|
<glyph unicode="”" horiz-adv-x="1032" d="M72 1436h393l-62 -613h-256zM567 1436h394l-74 -613h-256z" />
|
||||||
|
<glyph unicode="…" horiz-adv-x="1585" d="M1088 213q0 86 63.5 159.5t168 73.5t170 -73.5t65.5 -159.5q0 -96 -62.5 -158.5t-173.5 -62.5q-98 0 -164.5 67.5t-66.5 153.5zM559 213q0 86 63.5 159.5t168 73.5t170 -73.5t65.5 -159.5q0 -96 -62.5 -158.5t-173.5 -62.5q-98 0 -164.5 67.5t-66.5 153.5zM31 213 q0 86 63.5 159.5t168 73.5t170 -73.5t65.5 -159.5q0 -96 -62.5 -158.5t-173.5 -62.5q-98 0 -164.5 67.5t-66.5 153.5z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="333" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="415" />
|
||||||
|
<glyph unicode="" horiz-adv-x="1025" d="M0 1025h1025v-1025h-1025v1025z" />
|
||||||
|
</font>
|
||||||
|
</defs></svg>
|
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 201 B |
After Width: | Height: | Size: 233 B |
After Width: | Height: | Size: 89 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 102 B |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 180 B |
After Width: | Height: | Size: 168 B |
After Width: | Height: | Size: 205 B |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 107 B |
After Width: | Height: | Size: 855 B |
After Width: | Height: | Size: 101 B |