bye bye github
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
*.log
|
||||
*.swp
|
||||
cgisess_*
|
||||
Conf.pm
|
||||
5
dojo.conf
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
perldoc => 1,
|
||||
secrets => ['b8a9e54090ccb580b6203e53a9f9199af38ce538'],
|
||||
path => 'public',
|
||||
}
|
||||
46
lib/Dojo.pm
Normal file
@@ -0,0 +1,46 @@
|
||||
package Dojo;
|
||||
use Mojo::Base 'Mojolicious';
|
||||
use Dojo::Conf;
|
||||
use Dojo::Model::Vuelo;
|
||||
use Dojo::Model::Users;
|
||||
use Dojo::Model::Data;
|
||||
|
||||
# This method will run once at server start
|
||||
sub startup {
|
||||
my $self = shift;
|
||||
my $config = $self->plugin('Config'); #Config hash dojo.conf
|
||||
$self->plugin('PODRenderer') if $config->{perldoc}; #doc
|
||||
$self->secrets(['Mojojojo jojo']); #cookies
|
||||
|
||||
$self->helper(dbv => sub { state $dbv = Dojo::Model::Vuelo->new });
|
||||
$self->helper(dbg => sub { state $dbg = Dojo::Model::Users->new });
|
||||
$self->helper(ddtt => sub { state $ddtt = Dojo::Model::Data->new });
|
||||
$self->defaults({%Dojo::Conf::def});
|
||||
|
||||
my $r = $self->routes; #router
|
||||
|
||||
$r->any('/home')->to('home#home');
|
||||
$r->any('/cal')->to('home#cal');
|
||||
$r->any('/event/:id'=> [id => qr/\d+/])->to('home#event');
|
||||
#$r->any('/radio')->to('home#radio');
|
||||
$r->any('/pod')->to('home#podcast');
|
||||
$r->any('/store')->to('home#store');
|
||||
$r->any('/tv')->to('home#tv');
|
||||
$r->any('/contact')->to('home#contact');
|
||||
$r->any('/contact2')->to('home#contact2');
|
||||
$r->any('/pang')->to('home#pang');
|
||||
$r->any('/tst')->to('home#tst');
|
||||
|
||||
$r->any('/json/:dreq')->to('data#simple');
|
||||
$r->any('/json/candy/:command')->to('data#candy');
|
||||
|
||||
$r->any('/login')->to('users#login');
|
||||
$r->any('/logout')->to('users#logout');
|
||||
|
||||
my $logged_in = $r->under('/')->to('users#is_logged');
|
||||
$logged_in->get('/radio')->to('home#radio');
|
||||
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
48
lib/Dojo/Conf.pm.example
Normal file
@@ -0,0 +1,48 @@
|
||||
package Dojo::Conf;
|
||||
use strict;
|
||||
use warnings;
|
||||
#Paths
|
||||
use constant {
|
||||
MOD => "public", #location of modules
|
||||
SERVER_NAME => "localhost:3000",
|
||||
CHAT_SRV => "chat.vuelodegrulla.com",
|
||||
};
|
||||
|
||||
# database access
|
||||
use constant {
|
||||
VUELODB => "dbname",
|
||||
VUELODB_H => "localhost",
|
||||
VUELODB_UW => "writtername",
|
||||
VUELODB_UWP => "writterpass",
|
||||
VUELODB_UR => "readername",
|
||||
VUELODB_URP => "readerpass",
|
||||
};
|
||||
|
||||
our $radio ={ #hash to configure icecast radio
|
||||
server_name => SERVER_NAME,
|
||||
radio_server =>"https://myradio.com",
|
||||
channel => "/test",
|
||||
listen_url =>"http://radio:8000/test",
|
||||
};
|
||||
|
||||
our $chat={ #hash to configure chat (candy prodody) server
|
||||
chat_addr => "https://".CHAT_SRV,
|
||||
chat_srv => CHAT_SRV,
|
||||
chat_channel => 'Users@radio.'.CHAT_SRV,
|
||||
};
|
||||
our %rtmp={ #hash ro configure rtpm video server
|
||||
rtmp_server =>"rtmp://myserver.com/steam",
|
||||
rtmp_channel =>"channel",
|
||||
};
|
||||
|
||||
our %def=( #some other global configuration
|
||||
modules => MOD,
|
||||
# layout => "default"
|
||||
);
|
||||
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
|
||||
63
lib/Dojo/Controller/Data.pm
Normal file
@@ -0,0 +1,63 @@
|
||||
package Dojo::Controller::Data;
|
||||
use Mojo::Base 'Mojolicious::Controller';
|
||||
use Dojo::Support qw{ dmph merge_hash load_module };
|
||||
use Dojo::Conf;
|
||||
use Net::Telnet;
|
||||
|
||||
my $server_name = $Dojo::Conf::chat->{chat_srv};
|
||||
our $t; #telnet server object
|
||||
sub simple{
|
||||
my $c=shift;
|
||||
my $n=$c->param("dreq")//"";
|
||||
my $json = {status => "304"};
|
||||
$json = \%Dojo::Conf::radio if $n =~m/^radio$/ ;
|
||||
$json = candy() if $n =~m/^candy$/ ;
|
||||
$c->render(json=>$json);
|
||||
}
|
||||
|
||||
sub candy{
|
||||
my $c=shift;
|
||||
my $r="-1";
|
||||
if (connectT()) {
|
||||
if ($c->param("command") =~/^isOn$/){ $r = isOn(); }
|
||||
elsif( $c->session("pmid") == 4 ){
|
||||
$r = turnOn() if ($c->param("command") =~/^on$/);
|
||||
$r = turnOff() if ($c->param("command") =~/^off$/);
|
||||
}}
|
||||
else {$r="connection error";};
|
||||
$c->render(json => {a=>$r});
|
||||
}
|
||||
|
||||
sub turnOff{
|
||||
return 1 unless (isOn());
|
||||
grep(/Result: true/,sendT("host:deactivate('$server_name')"))?1:0;
|
||||
}
|
||||
sub turnOn{
|
||||
return 1 unless (!isOn());
|
||||
grep(/Result: true/,sendT("host:activate('$server_name')"))?1:0;
|
||||
}
|
||||
|
||||
sub isOn{ grep(/\s$server_name/,sendT("host:list()"))? 1:0; }
|
||||
|
||||
sub sendT{
|
||||
commandT(shift);
|
||||
my @r = $t->getlines(All=>0);
|
||||
disconnectT();
|
||||
return @r
|
||||
}
|
||||
sub connectT{
|
||||
$t = new Net::Telnet ( Port=>5582, Timeout=>1, Errmode=>'return' );
|
||||
# $t = new Net::Telnet ( Port=>5582, Timeout=>1, Errmode=>'die' );
|
||||
return 1 if $t->open();
|
||||
return 0;
|
||||
}
|
||||
sub commandT{
|
||||
$t->getlines(All=>0);#empty buffer
|
||||
$t->print(shift); #run istruction
|
||||
}
|
||||
sub disconnectT{ $t->close();}
|
||||
|
||||
1
|
||||
__END__
|
||||
|
||||
|
||||
12
lib/Dojo/Controller/Example.pm
Normal file
@@ -0,0 +1,12 @@
|
||||
package Dojo::Controller::Example;
|
||||
use Mojo::Base 'Mojolicious::Controller';
|
||||
|
||||
# This action will render a template
|
||||
sub welcome {
|
||||
my $self = shift;
|
||||
|
||||
# Render template "example/welcome.html.ep" with message
|
||||
$self->render(msg => 'Welcome to the Mojolicious real-time web framework!');
|
||||
}
|
||||
|
||||
1;
|
||||
99
lib/Dojo/Controller/Home.pm
Normal file
@@ -0,0 +1,99 @@
|
||||
package Dojo::Controller::Home;
|
||||
use Mojo::Base 'Mojolicious::Controller';
|
||||
use Dojo::Support qw{ dmph merge_hash load_module };
|
||||
use Dojo::Conf;
|
||||
|
||||
sub tst{
|
||||
my $c=shift;
|
||||
my ($v,$w)= load_module($c);
|
||||
# $c->stash($v);
|
||||
$c->stash(d =>$v);
|
||||
|
||||
}
|
||||
|
||||
sub home {
|
||||
my $c = shift;
|
||||
$c->stash((load_module($c))[0]);
|
||||
$c->stash( map{ $_->{nombre} => $_->{contenido}} @{$c->dbv->mod});
|
||||
}
|
||||
|
||||
sub pang {
|
||||
my $c = shift;
|
||||
my ($v,$w)=load_module($c);
|
||||
$c->stash($v);
|
||||
$c->stash( $c->dbv->pang($w) );
|
||||
}
|
||||
|
||||
sub cal {
|
||||
my $c = shift;
|
||||
$c->stash((load_module($c))[0]);
|
||||
my ($data,$block)=$c->dbv->cal;
|
||||
my %hdata;
|
||||
map{ push @{ $hdata{$_->{bid}} },$_; }(@$data);
|
||||
$c->stash( r=>\%hdata, b=>$block);
|
||||
}
|
||||
|
||||
sub event{
|
||||
my $c = shift;
|
||||
$c->stash((load_module($c))[0]);
|
||||
$c->stash(%{($c->dbv->event($c->param("id")))->[0]});
|
||||
}
|
||||
sub contact{
|
||||
my $c = shift;
|
||||
if ($c->param("mup")){
|
||||
$c->flash(mname => $c->param("mname"));
|
||||
$c->redirect_to('contact2');
|
||||
}else{
|
||||
my $dir= "/$c->{stash}{controller}/$c->{stash}{action}";
|
||||
$c->stash( css=>["$dir/cssContact1.css"], js=>[]);
|
||||
$c->stash( layout=>"default");
|
||||
}
|
||||
}
|
||||
|
||||
sub contact2{
|
||||
my $c = shift;
|
||||
$c->redirect_to("home") unless $c->flash('mname');
|
||||
my $dir= "/$c->{stash}{controller}/contact";
|
||||
$c->stash( css=>["$dir/cssContact2.css"], js=>[]);
|
||||
$c->stash( layout=>"default");
|
||||
$c->stash( mname=>$c->flash('mname'));
|
||||
}
|
||||
|
||||
sub store{
|
||||
my $c = shift;
|
||||
$c->stash((load_module($c))[0]);
|
||||
$c->stash( r=>$c->dbv->store);
|
||||
}
|
||||
|
||||
sub tv{
|
||||
my $c = shift;
|
||||
$c->stash( merge_hash(
|
||||
(load_module($c))[0],
|
||||
(load_module($c,"home/tv/trans"))[0]
|
||||
));
|
||||
my ($series,$table)=$c->dbv->tv;
|
||||
$c->stash( series=>$series, table=>$table);
|
||||
}
|
||||
|
||||
sub podcast{
|
||||
my $c = shift;
|
||||
$c->stash((load_module($c))[0]);
|
||||
|
||||
my ($txt,$h)=$c->dbv->podcast;
|
||||
$c->stash( t=>$txt, pod=>$h,);
|
||||
}
|
||||
|
||||
sub radio{
|
||||
my $c=shift;
|
||||
$c->stash((load_module($c))[0]);
|
||||
$c->stash(%{($c->dbv->radio)->[0]});
|
||||
$c->stash($Dojo::Conf::radio);
|
||||
$c->stash(nick=>$c->session("nick"));
|
||||
}
|
||||
|
||||
|
||||
#$c->render(text =>"$c->{match}->position");
|
||||
#$c->render(text=>"$c->{stash}{controller}");
|
||||
#$c->render(text=>"$c->{match}{stack}->[0]{controller}");
|
||||
#$c->render(text=>"$h->{css}[0]");
|
||||
1;
|
||||
28
lib/Dojo/Controller/Users.pm
Normal file
@@ -0,0 +1,28 @@
|
||||
package Dojo::Controller::Users;
|
||||
use Mojo::Base 'Mojolicious::Controller';
|
||||
use Dojo::Support qw{ merge_hash load_module };
|
||||
|
||||
|
||||
sub login {
|
||||
my $c = shift;
|
||||
$c->stash((load_module($c))[0]);
|
||||
my $user = $c->param('uname') // '';
|
||||
my $pass = $c->param('pass') //'';
|
||||
return $c->render unless my $pmid = $c->dbg->check($user, $pass);
|
||||
$c->session(user => $user, pmid=>$pmid, nick=> $c->param('nick'));
|
||||
$c->redirect_to('radio');
|
||||
}
|
||||
|
||||
sub is_logged {
|
||||
my $self = shift;
|
||||
return 1 if $self->session('user');
|
||||
$self->redirect_to('login');
|
||||
}
|
||||
|
||||
sub logout {
|
||||
my $self = shift;
|
||||
$self->session(expires => 1);
|
||||
$self->redirect_to('home');
|
||||
}
|
||||
|
||||
1;
|
||||
15
lib/Dojo/Model/Data.pm
Normal file
@@ -0,0 +1,15 @@
|
||||
package Dojo::Model::Data;
|
||||
use Dojo::Support qw{ dmph merge_hash load_module };
|
||||
use Dojo::Conf;
|
||||
|
||||
sub new { bless {}, shift };
|
||||
|
||||
|
||||
sub tst{
|
||||
|
||||
return {tst=>"this is my rifle"};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
38
lib/Dojo/Model/Users.pm
Normal file
@@ -0,0 +1,38 @@
|
||||
package Dojo::Model::Users;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use DBI;
|
||||
use Mojo::Util 'secure_compare';
|
||||
use Dojo::Conf;
|
||||
|
||||
|
||||
sub new { bless {}, shift }
|
||||
|
||||
sub check {
|
||||
my ($self, $user, $pass) = @_;
|
||||
my $q="select permiso_id as pid from usuario where nombre = ? and pass=? ";
|
||||
# | 0 | bloqueado |
|
||||
# | 1 | invitado |
|
||||
# | 2 | usuario |
|
||||
# | 3 | pago |
|
||||
# | 4 | master |
|
||||
my $r= _read($q,$vuelo,$user,$pass)->[0];
|
||||
return $r->{pid} // 0;
|
||||
}
|
||||
|
||||
sub _read{
|
||||
my ($q,$d,@bind)=@_;
|
||||
my (@empty,$arr);
|
||||
my $dbh = DBI->connect("DBI:mysql:".Dojo::Conf::GRULLADB.":".Dojo::Conf:: GRULLADB_H,Dojo::Conf::GRULLADB_UR,Dojo::Conf::GRULLADB_URP);
|
||||
return \@empty unless($dbh);
|
||||
#$dbh->do(qq{SET NAMES 'utf8'});
|
||||
my $h=$dbh->selectall_arrayref($q,{ Slice => {} },@bind);
|
||||
#((col1=>d1,col2=>d1),(col1=>d2,col2=>d2))
|
||||
$dbh->disconnect();
|
||||
return $h;
|
||||
}
|
||||
|
||||
|
||||
|
||||
1;
|
||||
79
lib/Dojo/Model/Vuelo.pm
Normal file
@@ -0,0 +1,79 @@
|
||||
package Dojo::Model::Vuelo;
|
||||
use Mojo::File 'path';
|
||||
use Mojo::JSON qw(decode_json encode_json);
|
||||
use Dojo::Support qw{ dmph merge_hash load_module };
|
||||
|
||||
use File::Basename;
|
||||
use Text::Markdown qw{ markdown };
|
||||
use Encode qw{ decode_utf8 };
|
||||
use DBI;
|
||||
use Dojo::Conf;
|
||||
|
||||
sub new { bless {}, shift };
|
||||
|
||||
|
||||
sub mod{
|
||||
my $q="select nombre,contenido from casa;";
|
||||
return \@{_read($q,$vuelo)};
|
||||
}
|
||||
|
||||
sub pang{
|
||||
my ($c,$q)=@_;
|
||||
return {map { basename($_,".md") => load_md("public/$_")}@{$q->{md}}};
|
||||
}
|
||||
sub cal {
|
||||
my $block=_read (path("public/home/cal/q1Block.q")->slurp,$vuelo);
|
||||
my $data=_read (path("public/home/cal/q3Event.q")->slurp,$vuelo);
|
||||
return ($data,$block);
|
||||
}
|
||||
|
||||
sub event{
|
||||
my ($self,$id)=@_;
|
||||
return _read (path("public/home/event/qEvent.q")->slurp,$vuelo,$id);
|
||||
}
|
||||
|
||||
sub store{
|
||||
return _read (path("public/home/store/qStore.q")->slurp,$vuelo);
|
||||
}
|
||||
|
||||
sub tv{
|
||||
my $series = _read (path("public/home/tv/qSeries.q")->slurp,$vuelo); #group,name
|
||||
my $table = _read (path("public/home/tv/qTable.q")->slurp,$vuelo); #name,order,group
|
||||
return ($series,$table);
|
||||
}
|
||||
|
||||
sub podcast{
|
||||
my $txt = path("public/home/podcast/text.txt")->slurp;
|
||||
my $hash = decode_json path("public/home/podcast/jsonPod.json")->slurp;
|
||||
return ($txt,$hash);
|
||||
}
|
||||
|
||||
sub radio{
|
||||
my $q="select contenido as rmod from casa where nombre='rmod';";
|
||||
return _read($q,$vuelo);
|
||||
}
|
||||
|
||||
sub _read{
|
||||
my ($q,$d,@bind)=@_;
|
||||
my (@empty,$arr);
|
||||
my $dbh = DBI->connect("DBI:mysql:".Dojo::Conf::VUELODB.":".Dojo::Conf::VUELODB_H,Dojo::Conf::VUELODB_UR,Dojo::Conf::VUELODB_URP);
|
||||
return \@empty unless($dbh);
|
||||
#$dbh->do(qq{SET NAMES 'utf8'});
|
||||
my $h=$dbh->selectall_arrayref($q,{ Slice => {} },@bind);
|
||||
#((col1=>d1,col2=>d1),(col1=>d2,col2=>d2))
|
||||
$dbh->disconnect();
|
||||
return $h;
|
||||
}
|
||||
|
||||
sub load_md{
|
||||
return "" unless
|
||||
my $text = path(shift)->slurp;
|
||||
return markdown( decode_utf8($text) );
|
||||
}
|
||||
|
||||
sub load_txt{
|
||||
return "" unless
|
||||
my $text = path(shift)->slurp;
|
||||
return decode_utf8($text);
|
||||
}
|
||||
|
||||
62
lib/Dojo/Support.pm
Normal file
@@ -0,0 +1,62 @@
|
||||
package Dojo::Support;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Exporter 'import';
|
||||
our @EXPORT = qw/ dmph merge_hash load_module /;
|
||||
use Mojo::Base 'Mojolicious';
|
||||
|
||||
use File::Basename;
|
||||
use Mojo::File 'path';
|
||||
use Path::Class;
|
||||
use Encode qw{ decode_utf8 };
|
||||
use Hash::Merge;
|
||||
use Dojo::Conf;
|
||||
|
||||
|
||||
|
||||
sub get_names{
|
||||
my $dir = shift;
|
||||
my @file_name;
|
||||
opendir(DIR, $dir) or die "error opening dir: $dir \n$!";
|
||||
while (my $file = readdir(DIR)) {
|
||||
next unless ( $file =~m/^[\w\d]/);
|
||||
next unless (-f "$dir/$file");
|
||||
push(@file_name,$file);
|
||||
}
|
||||
closedir(DIR);
|
||||
return sort @file_name;
|
||||
};
|
||||
|
||||
sub merge_hash{
|
||||
my ($v,$w)=@_;
|
||||
my $merger = Hash::Merge->new('LEFT_PRECEDENT');
|
||||
return $merger->merge( $v, $w );
|
||||
}
|
||||
|
||||
sub load_module{
|
||||
my $c=shift;
|
||||
my $dir=shift //"$c->{stash}{controller}/$c->{stash}{action}";
|
||||
my $lpath= Dojo::Conf::MOD."/$dir";
|
||||
my $h; $h->{js}=[]; $h->{css}=[]; #no me gusta!!!
|
||||
$h->{layout} = "default";
|
||||
my $q;
|
||||
my @s= get_names($lpath);
|
||||
foreach (@s) {
|
||||
push(@{$h->{$1}}, "/$dir/$_") if /.*\.(css|js)$/;
|
||||
push(@{$q->{$1}}, "/$dir/$_") if /.*\.(q|json|txt|md)$/;
|
||||
}
|
||||
return ($h,$q);
|
||||
};
|
||||
|
||||
|
||||
sub dmph{
|
||||
my $x = shift;
|
||||
my $y=" ";
|
||||
foreach (sort(keys %$x)) {
|
||||
$y= "$y $_ = $x->{$_} \n";
|
||||
}
|
||||
return $y;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
56
public/ext/candy/CONTRIBUTING.md
Executable file
@@ -0,0 +1,56 @@
|
||||
# Contributing
|
||||
|
||||
## Team members
|
||||
|
||||
* Patrick Stadler · [@pstadler](http://twitter.com/pstadler) · <patrick.stadler@gmail.com>
|
||||
* Michael Weibel · [@weibelm](htps://twitter.com/weibelm) · <michael.weibel@gmail.com>
|
||||
|
||||
## Learn & listen
|
||||
|
||||
[](https://gitter.im/candy-chat)
|
||||
|
||||
* [Mailing list](http://groups.google.com/group/candy-chat)
|
||||
* yes, non-gmail users can signup as well
|
||||
* [FAQ](https://github.com/candy-chat/candy/wiki/Frequently-Asked-Questions)
|
||||
|
||||
## Contributing
|
||||
|
||||
You want to help us? **Awesome!**
|
||||
|
||||
### How to contribute
|
||||
A few hopefully helpful hints to contributing to Candy
|
||||
|
||||
#### Using vagrant
|
||||
1. [Fork](https://help.github.com/articles/fork-a-repo) Candy
|
||||
2. [Install Vagrant](http://vagrantup.com/)
|
||||
3. Run `vagrant up`.
|
||||
5. Create a branch based on the `master` branch (`git checkout -B my-awesome-feature`)
|
||||
6. Run `grunt watch` to automatically run jshint (syntax checker) and the build of `candy.bundle.js` and `candy.min.js` while developing.
|
||||
7. Make your changes, fix eventual *jshint* errors & push them back to your fork
|
||||
8. Create a [pull request](https://help.github.com/articles/using-pull-requests)
|
||||
|
||||
|
||||
#### On your own machine
|
||||
Please note that you should have a working XMPP server to test your changes (the vagrant way does already have a working XMPP server).
|
||||
|
||||
1. [Fork](https://help.github.com/articles/fork-a-repo) Candy
|
||||
2. Clone your fork
|
||||
3. Checkout out `master` branch (`git checkout master`)
|
||||
4. Install [Node.js](http://nodejs.org/)
|
||||
5. Install [Grunt](http://gruntjs.com/) (`npm install -g grunt-cli`)
|
||||
6. Install [Bower](http://bower.io/) (`npm install -g bower`)
|
||||
7. Install npm dependencies (`npm install` in candy root directory)
|
||||
8. Install bower dependencies (`bower install` in candy root directory)
|
||||
9. Create a branch based on the `master` branch (`git checkout -B my-awesome-feature`)
|
||||
10. Run `grunt watch` to automatically run jshint (syntax checker) and the build of `candy.bundle.js` and `candy.min.js` while developing.
|
||||
11. Make your changes, fix eventual *jshint* errors & push them back to your fork
|
||||
12. Create a [pull request](https://help.github.com/articles/using-pull-requests)
|
||||
|
||||
In case you have any questions, don't hesitate to ask on the [Mailing list](http://groups.google.com/group/candy-chat).
|
||||
|
||||
### Running tests
|
||||
|
||||
* Tests are run using [Intern](http://theintern.io).
|
||||
* `grunt` and `grunt watch` will each run unit tests in Chrome on Linux (for fast feedback).
|
||||
* `grunt test` will run both unit and integration tests in a variety of environments. Tests are run using Selenium Standalone and Phantom.JS while developing, and on Sauce Labs in CI or using `grunt test`.
|
||||
* If you don't want to use the Vagrant box to run Selenium/PhantomJS, set `CANDY_VAGRANT='false'` to run tests.
|
||||
9
public/ext/candy/CREDITS.md
Executable file
@@ -0,0 +1,9 @@
|
||||
Credits
|
||||
=======
|
||||
- [Special thanks to our contributors](https://github.com/candy-chat/candy/graphs/contributors)
|
||||
- [famfamfam silk icons](http://www.famfamfam.com/lab/icons/silk/) is a smooth, free icon set, containing over 700 16-by-16 pixel icons.
|
||||
- [Simple Smileys](http://simplesmileys.org) are beautifully simple emoticons.
|
||||
- [Flash MP3 Player](http://flash-mp3-player.net/players/js) is a very simple flash audio player used by Candy for audio notifications.
|
||||
- [Colin Snover](http://zetafleet.com/blog/javascript-dateparse-for-iso-8601) provides a fix for browsers not supporting latest Date.parse().
|
||||
- [Ben Cherry](http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth) wrote a great article about the JS module pattern.
|
||||
- [Amiado Group](http://www.amiadogroup.com) allowed us to make Candy freely available for everyone :)
|
||||
9
public/ext/candy/LICENSE
Executable file
@@ -0,0 +1,9 @@
|
||||
Copyright (c) 2011 Amiado Group AG
|
||||
Copyright (c) 2012-2014 Patrick Stadler & Michael Weibel
|
||||
Copyright (c) 2015 Adhearsion Foundation Inc <info@adhearsion.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
28
public/ext/candy/README.md
Executable file
@@ -0,0 +1,28 @@
|
||||
Candy — a JavaScript-based multi-user chat client
|
||||
==================================================
|
||||
|
||||
[](https://travis-ci.org/candy-chat/candy)
|
||||
[](https://coveralls.io/r/candy-chat/candy)
|
||||
|
||||
Visit the official project page: http://candy-chat.github.io/candy
|
||||
|
||||
Features
|
||||
--------
|
||||
- Focused on real-time multi-user chatting
|
||||
- Easy to configure, easy to run, easy to use
|
||||
- Highly customizable
|
||||
- 100% well-documented JavaScript source code
|
||||
- Built for Jabber (XMPP), using famous technologies
|
||||
- Used and approved in a productive environment with up to 400 concurrent users
|
||||
- Works with all major web browsers including IE9
|
||||
|
||||
Plugins
|
||||
-------
|
||||
If you wish to add new functionality (to your candy installation) or contribute plugins, take a look at our [plugin repository](http://github.com/candy-chat/candy-plugins).
|
||||
|
||||
Support & Community
|
||||
-------------------
|
||||
Take a look at our [FAQ](https://github.com/candy-chat/candy/wiki/Frequently-Asked-Questions). If it doesn't solve your questions, you're welcome to join our [Mailinglist on Google Groups](http://groups.google.com/group/candy-chat).
|
||||
You don't need to have a Gmail account for it.
|
||||
|
||||
[](http://githalytics.com/candy-chat/candy)
|
||||
41
public/ext/candy/bower.json
Executable file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "candy",
|
||||
"version": "2.2.0",
|
||||
"homepage": "http://candy-chat.github.io/candy/",
|
||||
"authors": [
|
||||
"Michael Weibel <michael.weibel@gmail.com>",
|
||||
"Patrick Stadler <patrick.stadler@gmail.com>"
|
||||
],
|
||||
"description": "Multi-user XMPP web client",
|
||||
"main": [
|
||||
"candy.min.js"
|
||||
],
|
||||
"keywords": [
|
||||
"xmpp",
|
||||
"muc",
|
||||
"multi-user",
|
||||
"websocket",
|
||||
"bosh",
|
||||
"chat"
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/candy-chat/candy.git"
|
||||
},
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"jquery": "~1.10.2",
|
||||
"strophe": "1.1.3",
|
||||
"strophejs-plugins": "benlangfeld/strophejs-plugins#30fb089457addc37e01d69c3536dee868a90a9ad",
|
||||
"mustache": "0.3.0",
|
||||
"jquery-i18n": "1.1.1",
|
||||
"bootstrap": "~3.3.6"
|
||||
}
|
||||
}
|
||||
6680
public/ext/candy/candy.bundle.js
Executable file
1
public/ext/candy/candy.bundle.map
Executable file
5
public/ext/candy/candy.min.js
vendored
Executable file
1
public/ext/candy/candy.min.map
Executable file
4
public/ext/candy/example/htaccess
Executable file
@@ -0,0 +1,4 @@
|
||||
AddDefaultCharset UTF-8
|
||||
Options +MultiViews
|
||||
RewriteEngine On
|
||||
RewriteRule http-bind/ http://localhost:5280/http-bind/ [P]
|
||||
51
public/ext/candy/example/index.html
Executable file
@@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Candy - Chats are not dead yet</title>
|
||||
<link rel="shortcut icon" href="../res/img/favicon.png" type="image/gif" />
|
||||
<link rel="stylesheet" type="text/css" href="../libs.min.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../res/default.css" />
|
||||
|
||||
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../libs.min.js"></script>
|
||||
<script type="text/javascript" src="../candy.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
Candy.init('http-bind/', {
|
||||
core: {
|
||||
// only set this to true if developing / debugging errors
|
||||
debug: false,
|
||||
// autojoin is a *required* parameter if you don't have a plugin (e.g. roomPanel) for it
|
||||
// true
|
||||
// -> fetch info from server (NOTE: does only work with openfire server)
|
||||
// ['test@conference.example.com']
|
||||
// -> array of rooms to join after connecting
|
||||
autojoin: true
|
||||
},
|
||||
view: { assets: '../res/' }
|
||||
});
|
||||
|
||||
Candy.Core.connect();
|
||||
|
||||
/**
|
||||
* Thanks for trying Candy!
|
||||
*
|
||||
* If you need more information, please see here:
|
||||
* - Setup instructions & config params: http://candy-chat.github.io/candy/#setup
|
||||
* - FAQ & more: https://github.com/candy-chat/candy/wiki
|
||||
*
|
||||
* Mailinglist for questions:
|
||||
* - http://groups.google.com/group/candy-chat
|
||||
*
|
||||
* Github issues for bugs:
|
||||
* - https://github.com/candy-chat/candy/issues
|
||||
*/
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="candy"></div>
|
||||
</body>
|
||||
</html>
|
||||
6760
public/ext/candy/libs.bundle.css
Executable file
6782
public/ext/candy/libs.bundle.js
Executable file
1
public/ext/candy/libs.bundle.map
Executable file
5
public/ext/candy/libs.min.css
vendored
Executable file
3
public/ext/candy/libs.min.js
vendored
Executable file
65
public/ext/candy/package.json
Executable file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "candy",
|
||||
"version": "2.2.0",
|
||||
"description": "Multi-user XMPP web client",
|
||||
"main": "candy.min.js",
|
||||
"directories": {
|
||||
"doc": "docs",
|
||||
"example": "example"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/candy-chat/candy.git"
|
||||
},
|
||||
"keywords": [
|
||||
"xmpp",
|
||||
"muc",
|
||||
"multi-user",
|
||||
"websocket",
|
||||
"bosh",
|
||||
"chat"
|
||||
],
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Michael Weibel",
|
||||
"email": "michael.weibel@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Patrick Stadler",
|
||||
"email": "patrick.stadler@gmail.com",
|
||||
"url": "http://pstadler.sh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/candy-chat/candy/issues"
|
||||
},
|
||||
"homepage": "http://candy-chat.github.io/candy/",
|
||||
"devDependencies": {
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-clear": "^0.2.1",
|
||||
"grunt-contrib-clean": "^0.5.0",
|
||||
"grunt-contrib-compress": "^0.13.0",
|
||||
"grunt-contrib-concat": "^0.5.1",
|
||||
"grunt-contrib-cssmin": "^0.14.0",
|
||||
"grunt-contrib-jshint": "^0.10.0",
|
||||
"grunt-contrib-uglify": "^0.4.0",
|
||||
"grunt-contrib-watch": "^0.6.1",
|
||||
"grunt-coveralls": "^0.3.0",
|
||||
"grunt-github-releaser": "^0.1.17",
|
||||
"grunt-mkdir": "^0.1.1",
|
||||
"grunt-natural-docs": "^0.1.1",
|
||||
"grunt-notify": "^0.3.0",
|
||||
"grunt-prompt": "^1.3.0",
|
||||
"grunt-sync-pkg": "^0.1.2",
|
||||
"grunt-todo": "~0.4.0",
|
||||
"intern": "^2.0.1",
|
||||
"jshint-stylish": "^0.2.0",
|
||||
"lolex": "^1.2.0",
|
||||
"sinon": "^1.10.3",
|
||||
"sinon-chai": "^2.5.0"
|
||||
}
|
||||
}
|
||||
803
public/ext/candy/res/default.css
Executable file
@@ -0,0 +1,803 @@
|
||||
/** File: default.css
|
||||
* Candy - Chats are not dead yet.
|
||||
*
|
||||
* Legal: See the LICENSE file at the top-level directory of this distribution and at https://github.com/candy-chat/candy/blob/master/LICENSE
|
||||
*/
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Helvetica Neue', Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
#candy {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
background-color: #444;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#chat-tabs {
|
||||
list-style: none;
|
||||
margin: 0 200px 0 0;
|
||||
padding: 0;
|
||||
overflow: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
#chat-tabs li {
|
||||
margin: 0;
|
||||
float: left;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
margin: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
#chat-tabs a {
|
||||
padding: 4px 50px 4px 10px;
|
||||
display: inline-block;
|
||||
color: #ccc;
|
||||
height: 20px;
|
||||
background-color: #666;
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
|
||||
#chat-tabs .active a {
|
||||
background-color: #eee;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#chat-tabs .transition {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background: url(img/tab-transitions.png) repeat-y left;
|
||||
border-radius: 0 3px 0 0;
|
||||
}
|
||||
|
||||
#chat-tabs a.close {
|
||||
background-color: transparent;
|
||||
position: absolute;
|
||||
right: -2px;
|
||||
top: -3px;
|
||||
height: auto;
|
||||
padding: 5px;
|
||||
margin: 0 5px 0 2px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
#chat-tabs .active .transition {
|
||||
background: url(img/tab-transitions.png) repeat-y -50px;
|
||||
}
|
||||
|
||||
#chat-tabs .close:hover {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#chat-tabs .unread {
|
||||
color: white;
|
||||
background-color: #9b1414;
|
||||
padding: 2px 4px;
|
||||
font-weight: bold;
|
||||
font-size: 10px;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 22px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#chat-tabs .offline .label {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
#chat-toolbar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
width: 200px;
|
||||
height: 24px;
|
||||
padding-top: 7px;
|
||||
background-color: #444;
|
||||
display: none;
|
||||
border-top: 1px solid black;
|
||||
box-shadow: 0 1px 0 0 #555 inset;
|
||||
}
|
||||
|
||||
#chat-toolbar li {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: 5px;
|
||||
float: left;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
background-position: top left;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#chat-toolbar #emoticons-icon {
|
||||
background-image: url(img/action/emoticons.png);
|
||||
}
|
||||
|
||||
#chat-toolbar .context {
|
||||
background-image: url(img/action/settings.png);
|
||||
display: none;
|
||||
}
|
||||
|
||||
.role-moderator #chat-toolbar .context, .affiliation-owner #chat-toolbar .context {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#chat-sound-control {
|
||||
background-image: url(img/action/sound-off.png);
|
||||
}
|
||||
|
||||
#chat-sound-control.checked {
|
||||
background-image: url(img/action/sound-on.png);
|
||||
}
|
||||
|
||||
#chat-autoscroll-control {
|
||||
background-image: url(img/action/autoscroll-off.png);
|
||||
}
|
||||
|
||||
#chat-autoscroll-control.checked {
|
||||
background-image: url(img/action/autoscroll-on.png);
|
||||
}
|
||||
|
||||
#chat-statusmessage-control {
|
||||
background-image: url(img/action/statusmessage-off.png);
|
||||
}
|
||||
|
||||
#chat-statusmessage-control.checked {
|
||||
background-image: url(img/action/statusmessage-on.png);
|
||||
}
|
||||
|
||||
#chat-toolbar .usercount {
|
||||
background-image: url(img/action/usercount.png);
|
||||
cursor: default;
|
||||
padding-left: 20px;
|
||||
width: auto;
|
||||
margin-right: 5px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.usercount span {
|
||||
display: inline-block;
|
||||
padding: 1px 3px;
|
||||
background-color: #666;
|
||||
font-weight: bold;
|
||||
border-radius: 3px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.room-pane {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.roster-pane {
|
||||
position: absolute;
|
||||
overflow: auto;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 200px;
|
||||
margin: 30px 0 31px 0;
|
||||
background-color: #333;
|
||||
border-top: 1px solid black;
|
||||
box-shadow: inset 0 1px 0 0 #555;
|
||||
}
|
||||
|
||||
.roster-pane .user {
|
||||
cursor: pointer;
|
||||
padding: 7px 10px;
|
||||
font-size: 12px;
|
||||
opacity: 0;
|
||||
display: none;
|
||||
color: #ccc;
|
||||
clear: both;
|
||||
height: 14px;
|
||||
border-bottom: 1px solid black;
|
||||
box-shadow: 0 1px 0 0 #555;
|
||||
}
|
||||
|
||||
.roster-pane .user:hover {
|
||||
background-color: #222;
|
||||
}
|
||||
|
||||
.roster-pane .user.status-ignored {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.roster-pane .user.me {
|
||||
font-weight: bold;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.roster-pane .user.me:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.roster-pane .label {
|
||||
float: left;
|
||||
width: 110px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-shadow: 1px 1px black;
|
||||
}
|
||||
|
||||
.roster-pane li {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
float: right;
|
||||
display: block;
|
||||
margin-left: 3px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.roster-pane li.role {
|
||||
cursor: default;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.roster-pane li.role-moderator {
|
||||
background-image: url(img/roster/role-moderator.png);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.roster-pane li.affiliation-owner {
|
||||
background-image: url(img/roster/affiliation-owner.png);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.roster-pane li.ignore {
|
||||
background-image: url(img/roster/ignore.png);
|
||||
display: none;
|
||||
}
|
||||
|
||||
.roster-pane .status-ignored li.ignore {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.roster-pane li.context {
|
||||
color: #999;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.roster-pane li.context:hover {
|
||||
background-color: #666;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.roster-pane .me li.context {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message-pane-wrapper {
|
||||
clear: both;
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: auto;
|
||||
width: auto;
|
||||
margin: 30px 200px 31px 0;
|
||||
background-color: #eee;
|
||||
font-size: 13px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.message-pane {
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.message-pane li {
|
||||
cursor: default;
|
||||
border-bottom: 1px solid #ccc;
|
||||
box-shadow: 0 1px 0 0 white;
|
||||
}
|
||||
|
||||
.message-pane small {
|
||||
display: none;
|
||||
color: #a00;
|
||||
font-size: 10px;
|
||||
position: absolute;
|
||||
background-color: #f7f7f7;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
margin: 4px 0;
|
||||
padding: 0 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.message-pane li:hover {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.message-pane li:hover small {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.message-pane li>div {
|
||||
overflow: auto;
|
||||
padding: 2px 0 2px 130px;
|
||||
line-height: 24px;
|
||||
white-space: -o-pre-wrap; /* Opera */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
.message-pane li>div p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.message-pane .label {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
display: block;
|
||||
margin-left: -130px;
|
||||
width: 110px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.message-pane .label:hover,
|
||||
.message-pane .label:focus {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.message-pane .spacer {
|
||||
color: #aaa;
|
||||
font-weight: bold;
|
||||
margin-left: -14px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.message-pane .subject, .message-pane .subject .label {
|
||||
color: #a00;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.message-pane .adminmessage {
|
||||
color: #a00;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.message-pane .infomessage {
|
||||
color: #888;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.message-pane div>a {
|
||||
color: #a00;
|
||||
}
|
||||
|
||||
.message-pane a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.message-pane .emoticon {
|
||||
vertical-align: text-bottom;
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.message-form-wrapper {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: auto;
|
||||
margin-right: 200px;
|
||||
border-top: 1px solid #ccc;
|
||||
background-color: white;
|
||||
height: 31px;
|
||||
}
|
||||
|
||||
.message-form {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-right: 320px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.message-form input {
|
||||
border: 0 none;
|
||||
padding: 5px 10px;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
display: block;
|
||||
outline-width: 0;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.message-form input.submit {
|
||||
cursor: pointer;
|
||||
background-color: #ccc;
|
||||
color: #666;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
margin: 3px 203px 3px 3px;
|
||||
padding: 0 10px;
|
||||
width: auto;
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
height: 25px;
|
||||
font-weight: bold;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#tooltip {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: none;
|
||||
margin: 13px -18px -3px -2px;
|
||||
color: #333;
|
||||
font-size: 11px;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
#tooltip div {
|
||||
background-color: #f7f7f7;
|
||||
padding: 2px 5px;
|
||||
zoom: 1;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .75);
|
||||
}
|
||||
|
||||
.arrow {
|
||||
background: url(img/tooltip-arrows.gif) no-repeat left bottom;
|
||||
height: 5px;
|
||||
display: block;
|
||||
position: relative;
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
.right-bottom .arrow-bottom {
|
||||
background-position: right bottom;
|
||||
}
|
||||
|
||||
.arrow-top {
|
||||
display: none;
|
||||
background-position: left top;
|
||||
}
|
||||
|
||||
.right-top .arrow-top {
|
||||
display: block;
|
||||
background-position: right top;
|
||||
}
|
||||
|
||||
.left-top .arrow-top {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
.left-top .arrow-bottom,
|
||||
.right-top .arrow-bottom {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#context-menu {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: none;
|
||||
padding: 5px 10px;
|
||||
margin: 13px -28px -3px -12px;
|
||||
}
|
||||
|
||||
#context-menu ul {
|
||||
background-color: #f7f7f7;
|
||||
color: #333;
|
||||
font-size: 12px;
|
||||
padding: 2px;
|
||||
zoom: 1;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .75);
|
||||
}
|
||||
|
||||
#context-menu li {
|
||||
padding: 3px 5px 3px 20px;
|
||||
line-height: 12px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 2px;
|
||||
background: 1px no-repeat;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#context-menu li:hover {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
#context-menu li:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#context-menu .private {
|
||||
background-image: url(img/action/private.png);
|
||||
}
|
||||
|
||||
#context-menu .ignore {
|
||||
background-image: url(img/action/ignore.png);
|
||||
}
|
||||
|
||||
#context-menu .unignore {
|
||||
background-image: url(img/action/unignore.png);
|
||||
}
|
||||
|
||||
#context-menu .kick {
|
||||
background-image: url(img/action/kick.png);
|
||||
}
|
||||
|
||||
#context-menu .ban {
|
||||
background-image: url(img/action/ban.png);
|
||||
}
|
||||
|
||||
#context-menu .subject {
|
||||
background-image: url(img/action/subject.png);
|
||||
}
|
||||
|
||||
#context-menu .emoticons {
|
||||
padding-left: 5px;
|
||||
width: 85px;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
#context-menu .emoticons:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#context-menu .emoticons img {
|
||||
cursor: pointer;
|
||||
margin: 3px;
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
#chat-modal.modal-common {
|
||||
background: #eee;
|
||||
width: 300px;
|
||||
padding: 20px 5px;
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-left: -160px;
|
||||
margin-top: -45px;
|
||||
text-align: center;
|
||||
display: none;
|
||||
z-index: 100;
|
||||
border: 5px solid #888;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 5px black;
|
||||
}
|
||||
|
||||
#chat-modal-overlay {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 90;
|
||||
background-image: url(img/overlay.png);
|
||||
}
|
||||
|
||||
#chat-modal.modal-login {
|
||||
display: block;
|
||||
margin-top: -100px;
|
||||
}
|
||||
|
||||
#chat-modal-spinner {
|
||||
display: none;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#chat-modal form {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
#chat-modal label, #chat-modal input, #chat-modal select {
|
||||
display: block;
|
||||
float: left;
|
||||
line-height: 26px;
|
||||
font-size: 16px;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
#chat-modal input, #chat-modal select {
|
||||
padding: 2px;
|
||||
line-height: 16px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
#chat-modal input[type='text'],
|
||||
#chat-modal input[type='password'] {
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
padding: 4px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
#chat-modal.login-with-domains {
|
||||
width: 650px;
|
||||
margin-left: -330px;
|
||||
}
|
||||
|
||||
#chat-modal span.at-symbol {
|
||||
float: left;
|
||||
padding: 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#chat-modal select[name=domain] {
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
#chat-modal label {
|
||||
text-align: right;
|
||||
padding-right: 1em;
|
||||
clear: both;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#chat-modal input.button {
|
||||
float: none;
|
||||
display: block;
|
||||
margin: 5px auto;
|
||||
clear: both;
|
||||
position: relative;
|
||||
top: 10px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#chat-modal .close {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
display: none;
|
||||
padding: 0 5px;
|
||||
margin: -17px 3px 0 0;
|
||||
color: #999;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#chat-modal .close:hover {
|
||||
color: #333;
|
||||
background-color: #aaa;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap Responsive Design styles
|
||||
* It add styles to every element so we need to override some to keep the look of Candy
|
||||
*/
|
||||
*, :after, :before {
|
||||
-webkit-box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
label {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 100%;
|
||||
font-weight: normal;
|
||||
text-align: left;
|
||||
line-height: inherit;
|
||||
padding: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.close {
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
opacity: 1;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
#mobile-roster-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* Responsive specific styles for devices under 600px
|
||||
* Mainly changing the size of room, roster and message panes when opened / closed
|
||||
*/
|
||||
@media (max-width: 599px) {
|
||||
.room-pane .message-pane-wrapper {
|
||||
margin-right: 50px;
|
||||
}
|
||||
|
||||
.room-pane:not(.open) .roster-pane {
|
||||
right: -150px;
|
||||
}
|
||||
|
||||
.roster-pane {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.message-pane li>div {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.message-pane li>div.infomessage {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.message-pane .label {
|
||||
width: auto;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.message-pane .spacer {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.room-pane:not(.open) .message-form-wrapper {
|
||||
margin-right: 50px;
|
||||
}
|
||||
|
||||
.room-pane:not(.open) .message-form {
|
||||
margin-right: 150px;
|
||||
}
|
||||
|
||||
.room-pane:not(.open) .message-form input.submit {
|
||||
margin-right: 53px;
|
||||
}
|
||||
|
||||
#mobile-roster-icon {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* These are for the hamburger icon. The box-shadow adds the extra lines
|
||||
*/
|
||||
.box-shadow-icon {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 50px;
|
||||
height: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.box-shadow-icon:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
top: 9px;
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
background: #aaa;
|
||||
box-shadow: 0 5px 0 0 #aaa, 0 10px 0 0 #aaa;
|
||||
}
|
||||
|
||||
.box-shadow-icon:hover {
|
||||
background: #222;
|
||||
}
|
||||
}
|
||||
BIN
public/ext/candy/res/img/action/autoscroll-off.png
Executable file
|
After Width: | Height: | Size: 442 B |
BIN
public/ext/candy/res/img/action/autoscroll-on.png
Executable file
|
After Width: | Height: | Size: 223 B |
BIN
public/ext/candy/res/img/action/ban.png
Executable file
|
After Width: | Height: | Size: 796 B |
BIN
public/ext/candy/res/img/action/emoticons.png
Executable file
|
After Width: | Height: | Size: 725 B |
BIN
public/ext/candy/res/img/action/ignore.png
Executable file
|
After Width: | Height: | Size: 715 B |
BIN
public/ext/candy/res/img/action/kick.png
Executable file
|
After Width: | Height: | Size: 859 B |
BIN
public/ext/candy/res/img/action/menu.png
Executable file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
public/ext/candy/res/img/action/private.png
Executable file
|
After Width: | Height: | Size: 557 B |
BIN
public/ext/candy/res/img/action/settings.png
Executable file
|
After Width: | Height: | Size: 744 B |
BIN
public/ext/candy/res/img/action/sound-off.png
Executable file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
public/ext/candy/res/img/action/sound-on.png
Executable file
|
After Width: | Height: | Size: 544 B |
BIN
public/ext/candy/res/img/action/statusmessage-off.png
Executable file
|
After Width: | Height: | Size: 764 B |
BIN
public/ext/candy/res/img/action/statusmessage-on.png
Executable file
|
After Width: | Height: | Size: 659 B |
BIN
public/ext/candy/res/img/action/subject.png
Executable file
|
After Width: | Height: | Size: 413 B |
BIN
public/ext/candy/res/img/action/unignore.png
Executable file
|
After Width: | Height: | Size: 781 B |
BIN
public/ext/candy/res/img/action/usercount.png
Executable file
|
After Width: | Height: | Size: 753 B |
BIN
public/ext/candy/res/img/emoticons/Angel.png
Executable file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/ext/candy/res/img/emoticons/Angry.png
Executable file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/ext/candy/res/img/emoticons/Aww.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Aww_2.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Blushing.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Childish.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Confused.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Creepy.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Crying.png
Executable file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/ext/candy/res/img/emoticons/Cthulhu.png
Executable file
|
After Width: | Height: | Size: 775 B |
BIN
public/ext/candy/res/img/emoticons/Cute.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Cute_Winking.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Devil.png
Executable file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/ext/candy/res/img/emoticons/Gah.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Gah_2.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Gasping.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Greedy.png
Executable file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/ext/candy/res/img/emoticons/Grinning.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Grinning_Winking.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Happy.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Happy_2.png
Executable file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/ext/candy/res/img/emoticons/Happy_3.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Heart.png
Executable file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
public/ext/candy/res/img/emoticons/Huh.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Huh_2.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Laughing.png
Executable file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/ext/candy/res/img/emoticons/Lips_Sealed.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Madness.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Malicious.png
Executable file
|
After Width: | Height: | Size: 751 B |
2
public/ext/candy/res/img/emoticons/README
Executable file
@@ -0,0 +1,2 @@
|
||||
Simple Smileys is a set of 49 clean, free as in freedom, Public Domain smileys.
|
||||
For more packages or older versions, visit http://simplesmileys.org
|
||||
BIN
public/ext/candy/res/img/emoticons/Sick.png
Executable file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/ext/candy/res/img/emoticons/Smiling.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Speechless.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Spiteful.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Stupid.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Sunglasses.png
Executable file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/ext/candy/res/img/emoticons/Terrified.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Thumb_Down.png
Executable file
|
After Width: | Height: | Size: 572 B |
BIN
public/ext/candy/res/img/emoticons/Thumb_Up.png
Executable file
|
After Width: | Height: | Size: 530 B |
BIN
public/ext/candy/res/img/emoticons/Tired.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Tongue_Out.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Tongue_Out_Laughing.png
Executable file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/ext/candy/res/img/emoticons/Tongue_Out_Left.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Tongue_Out_Up.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Tongue_Out_Up_Left.png
Executable file
|
After Width: | Height: | Size: 704 B |
BIN
public/ext/candy/res/img/emoticons/Tongue_Out_Winking.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Uncertain.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Uncertain_2.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Unhappy.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/emoticons/Winking.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/ext/candy/res/img/favicon.png
Executable file
|
After Width: | Height: | Size: 490 B |
BIN
public/ext/candy/res/img/modal-spinner.gif
Executable file
|
After Width: | Height: | Size: 723 B |
BIN
public/ext/candy/res/img/overlay.png
Executable file
|
After Width: | Height: | Size: 109 B |
BIN
public/ext/candy/res/img/roster/affiliation-owner.png
Executable file
|
After Width: | Height: | Size: 670 B |