move static & templates to panikweb project directory
authorFrédéric Péters <fpeters@0d.be>
Wed, 8 Jul 2020 07:23:52 +0000 (09:23 +0200)
committerFrédéric Péters <fpeters@0d.be>
Wed, 8 Jul 2020 07:23:52 +0000 (09:23 +0200)
225 files changed:
panikweb/settings.py
panikweb/static/css/_general.scss [new file with mode: 0644]
panikweb/static/css/_grid.scss [new file with mode: 0644]
panikweb/static/css/_reset.scss [new file with mode: 0644]
panikweb/static/css/_specifics.scss [new file with mode: 0644]
panikweb/static/css/_type.scss [new file with mode: 0644]
panikweb/static/css/style.scss [new file with mode: 0644]
panikweb/static/fonts/Montserrat-Bold.ttf [new file with mode: 0644]
panikweb/static/fonts/Montserrat-Regular.ttf [new file with mode: 0644]
panikweb/static/img/LogoPanik.jpg [new file with mode: 0644]
panikweb/static/img/Radio_Panik_Logo_2016-01.png [new file with mode: 0644]
panikweb/static/img/actu.png [new file with mode: 0644]
panikweb/static/img/defaultLogo.png [new file with mode: 0644]
panikweb/static/img/emission.png [new file with mode: 0644]
panikweb/static/img/episode.png [new file with mode: 0644]
panikweb/static/img/favicon-16.png [new file with mode: 0644]
panikweb/static/img/favicon-32.png [new file with mode: 0644]
panikweb/static/img/favicon-48.png [new file with mode: 0644]
panikweb/static/img/favicon.png [new file with mode: 0644]
panikweb/static/img/logo-2016.png [new file with mode: 0644]
panikweb/static/img/logo-panik-500-invert.png [new file with mode: 0644]
panikweb/static/img/logo-panik-500.png [new file with mode: 0644]
panikweb/static/img/logo-panik.png [new file with mode: 0644]
panikweb/static/img/logo.jpg [new file with mode: 0644]
panikweb/static/img/logoPanik.png [new file with mode: 0644]
panikweb/static/img/logoPanikBW.png [new file with mode: 0644]
panikweb/static/img/sound.png [new file with mode: 0644]
panikweb/static/js/audioPlayer.js [new file with mode: 0644]
panikweb/static/js/jquery.scrollTo-1.4.3.1-min.js [new file with mode: 0644]
panikweb/static/js/konami.js [new file with mode: 0644]
panikweb/static/js/specifics.js [new file with mode: 0644]
panikweb/static/js/strophe.min.js [new file with mode: 0644]
panikweb/static/js/strophe.muc.js [new file with mode: 0644]
panikweb/static/reglo/RE01.otf [new file with mode: 0644]
panikweb/static/reglo/RE02-Medium.otf [new file with mode: 0644]
panikweb/static/reglo/RE03-Bold.otf [new file with mode: 0644]
panikweb/static/reglo/RE04-Bold.otf [new file with mode: 0644]
panikweb/static/reglo/RE05-Bold.otf [new file with mode: 0644]
panikweb/static/reglo/RE06.otf [new file with mode: 0644]
panikweb/static/reglo/RE07-Bold.otf [new file with mode: 0644]
panikweb/static/reglo/RESYMBOL-resized.otf [new file with mode: 0644]
panikweb/static/reglo/RESYMBOL.otf [new file with mode: 0644]
panikweb/static/reglo/Reglo-Bold.otf [new file with mode: 0644]
panikweb/static/reglo/Reglo-Bold.vfb [new file with mode: 0644]
panikweb/static/reglo/RegloScaleBold.otf [new file with mode: 0644]
panikweb/templates/404.html [new file with mode: 0644]
panikweb/templates/500.html [new file with mode: 0644]
panikweb/templates/agenda.html [new file with mode: 0644]
panikweb/templates/base.html [new file with mode: 0644]
panikweb/templates/chat.html [new file with mode: 0644]
panikweb/templates/combo/cells/alimentation/episode_auto_selection.html [new file with mode: 0644]
panikweb/templates/combo/cells/topik-large/link-cell.html [new file with mode: 0644]
panikweb/templates/combo/cells/topik/link-cell.html [new file with mode: 0644]
panikweb/templates/combo/gallerycell.html [new file with mode: 0644]
panikweb/templates/combo/page_template_about.html [new file with mode: 0644]
panikweb/templates/combo/page_template_full_width.html [new file with mode: 0644]
panikweb/templates/combo/page_template_sidebar.html [new file with mode: 0644]
panikweb/templates/combo/topik_menu_item.html [new file with mode: 0644]
panikweb/templates/emissions.html [new file with mode: 0644]
panikweb/templates/emissions/archives.html [new file with mode: 0644]
panikweb/templates/emissions/detail.html [new file with mode: 0644]
panikweb/templates/emissions/emission_detail.html [new file with mode: 0644]
panikweb/templates/emissions/episode_detail.html [new file with mode: 0644]
panikweb/templates/emissions/episodes.html [new file with mode: 0644]
panikweb/templates/emissions/nav.html [new file with mode: 0644]
panikweb/templates/emissions/newsitem_detail.html [new file with mode: 0644]
panikweb/templates/emissions/resume.html [new file with mode: 0644]
panikweb/templates/emissions/search_result.html [new file with mode: 0644]
panikweb/templates/episodes/detail.html [new file with mode: 0644]
panikweb/templates/episodes/inline.html [new file with mode: 0644]
panikweb/templates/episodes/resume.html [new file with mode: 0644]
panikweb/templates/episodes/search_result.html [new file with mode: 0644]
panikweb/templates/feed/newsitem.html [new file with mode: 0644]
panikweb/templates/feed/soundfile.html [new file with mode: 0644]
panikweb/templates/grid.html [new file with mode: 0644]
panikweb/templates/home.html [new file with mode: 0644]
panikweb/templates/includes/audio.html [new file with mode: 0644]
panikweb/templates/includes/metaNav.html [new file with mode: 0644]
panikweb/templates/includes/path.html [new file with mode: 0644]
panikweb/templates/includes/piwik.html [new file with mode: 0644]
panikweb/templates/includes/player.html [new file with mode: 0644]
panikweb/templates/includes/related.html [new file with mode: 0644]
panikweb/templates/includes/topik.html [new file with mode: 0644]
panikweb/templates/includes/week-nav.html [new file with mode: 0644]
panikweb/templates/includes/week.html [new file with mode: 0644]
panikweb/templates/listen.html [new file with mode: 0644]
panikweb/templates/listen/archives.html [new file with mode: 0644]
panikweb/templates/listen/nav.html [new file with mode: 0644]
panikweb/templates/news.html [new file with mode: 0644]
panikweb/templates/news/archives.html [new file with mode: 0644]
panikweb/templates/news/inline.html [new file with mode: 0644]
panikweb/templates/news/nav.html [new file with mode: 0644]
panikweb/templates/news/roll.html [new file with mode: 0644]
panikweb/templates/news/search_result.html [new file with mode: 0644]
panikweb/templates/newsletter/confirmation_email_body.txt [new file with mode: 0644]
panikweb/templates/newsletter/confirmation_email_subject.txt [new file with mode: 0644]
panikweb/templates/newsletter/done.html [new file with mode: 0644]
panikweb/templates/newsletter/subscriber_form.html [new file with mode: 0644]
panikweb/templates/newsletter/thanks.html [new file with mode: 0644]
panikweb/templates/nonstop_playlist.html [new file with mode: 0644]
panikweb/templates/panikdb/base.html [new file with mode: 0644]
panikweb/templates/panikombo/audio.html [new file with mode: 0644]
panikweb/templates/panikombo/episode.html [new file with mode: 0644]
panikweb/templates/panikombo/episode_auto_selection.html [new file with mode: 0644]
panikweb/templates/panikombo/newsitem_auto_selection.html [new file with mode: 0644]
panikweb/templates/panikombo/topik-cell.html [new file with mode: 0644]
panikweb/templates/party.html [new file with mode: 0644]
panikweb/templates/program.html [new file with mode: 0644]
panikweb/templates/search/search.html [new file with mode: 0644]
panikweb/templates/soundfiles/dialog-embed.html [new file with mode: 0644]
panikweb/templates/soundfiles/embed.html [new file with mode: 0644]
panikweb/templates/soundfiles/resume.html [new file with mode: 0644]
panikweb/templates/tpl-default.html [new file with mode: 0644]
panikweb_templates/static/css/_general.scss [deleted file]
panikweb_templates/static/css/_grid.scss [deleted file]
panikweb_templates/static/css/_reset.scss [deleted file]
panikweb_templates/static/css/_specifics.scss [deleted file]
panikweb_templates/static/css/_type.scss [deleted file]
panikweb_templates/static/css/style.scss [deleted file]
panikweb_templates/static/fonts/Montserrat-Bold.ttf [deleted file]
panikweb_templates/static/fonts/Montserrat-Regular.ttf [deleted file]
panikweb_templates/static/img/LogoPanik.jpg [deleted file]
panikweb_templates/static/img/Radio_Panik_Logo_2016-01.png [deleted file]
panikweb_templates/static/img/actu.png [deleted file]
panikweb_templates/static/img/defaultLogo.png [deleted file]
panikweb_templates/static/img/emission.png [deleted file]
panikweb_templates/static/img/episode.png [deleted file]
panikweb_templates/static/img/favicon-16.png [deleted file]
panikweb_templates/static/img/favicon-32.png [deleted file]
panikweb_templates/static/img/favicon-48.png [deleted file]
panikweb_templates/static/img/favicon.png [deleted file]
panikweb_templates/static/img/logo-2016.png [deleted file]
panikweb_templates/static/img/logo-panik-500-invert.png [deleted file]
panikweb_templates/static/img/logo-panik-500.png [deleted file]
panikweb_templates/static/img/logo-panik.png [deleted file]
panikweb_templates/static/img/logo.jpg [deleted file]
panikweb_templates/static/img/logoPanik.png [deleted file]
panikweb_templates/static/img/logoPanikBW.png [deleted file]
panikweb_templates/static/img/sound.png [deleted file]
panikweb_templates/static/js/audioPlayer.js [deleted file]
panikweb_templates/static/js/jquery.scrollTo-1.4.3.1-min.js [deleted file]
panikweb_templates/static/js/konami.js [deleted file]
panikweb_templates/static/js/specifics.js [deleted file]
panikweb_templates/static/js/strophe.min.js [deleted file]
panikweb_templates/static/js/strophe.muc.js [deleted file]
panikweb_templates/static/reglo/RE01.otf [deleted file]
panikweb_templates/static/reglo/RE02-Medium.otf [deleted file]
panikweb_templates/static/reglo/RE03-Bold.otf [deleted file]
panikweb_templates/static/reglo/RE04-Bold.otf [deleted file]
panikweb_templates/static/reglo/RE05-Bold.otf [deleted file]
panikweb_templates/static/reglo/RE06.otf [deleted file]
panikweb_templates/static/reglo/RE07-Bold.otf [deleted file]
panikweb_templates/static/reglo/RESYMBOL-resized.otf [deleted file]
panikweb_templates/static/reglo/RESYMBOL.otf [deleted file]
panikweb_templates/static/reglo/Reglo-Bold.otf [deleted file]
panikweb_templates/static/reglo/Reglo-Bold.vfb [deleted file]
panikweb_templates/static/reglo/RegloScaleBold.otf [deleted file]
panikweb_templates/templates/404.html [deleted file]
panikweb_templates/templates/500.html [deleted file]
panikweb_templates/templates/agenda.html [deleted file]
panikweb_templates/templates/base.html [deleted file]
panikweb_templates/templates/chat.html [deleted file]
panikweb_templates/templates/combo/cells/alimentation/episode_auto_selection.html [deleted file]
panikweb_templates/templates/combo/cells/topik-large/link-cell.html [deleted file]
panikweb_templates/templates/combo/cells/topik/link-cell.html [deleted file]
panikweb_templates/templates/combo/gallerycell.html [deleted file]
panikweb_templates/templates/combo/page_template_about.html [deleted file]
panikweb_templates/templates/combo/page_template_full_width.html [deleted file]
panikweb_templates/templates/combo/page_template_sidebar.html [deleted file]
panikweb_templates/templates/combo/topik_menu_item.html [deleted file]
panikweb_templates/templates/emissions.html [deleted file]
panikweb_templates/templates/emissions/archives.html [deleted file]
panikweb_templates/templates/emissions/detail.html [deleted file]
panikweb_templates/templates/emissions/emission_detail.html [deleted file]
panikweb_templates/templates/emissions/episode_detail.html [deleted file]
panikweb_templates/templates/emissions/episodes.html [deleted file]
panikweb_templates/templates/emissions/nav.html [deleted file]
panikweb_templates/templates/emissions/newsitem_detail.html [deleted file]
panikweb_templates/templates/emissions/resume.html [deleted file]
panikweb_templates/templates/emissions/search_result.html [deleted file]
panikweb_templates/templates/episodes/detail.html [deleted file]
panikweb_templates/templates/episodes/inline.html [deleted file]
panikweb_templates/templates/episodes/resume.html [deleted file]
panikweb_templates/templates/episodes/search_result.html [deleted file]
panikweb_templates/templates/feed/newsitem.html [deleted file]
panikweb_templates/templates/feed/soundfile.html [deleted file]
panikweb_templates/templates/grid.html [deleted file]
panikweb_templates/templates/home.html [deleted file]
panikweb_templates/templates/includes/audio.html [deleted file]
panikweb_templates/templates/includes/metaNav.html [deleted file]
panikweb_templates/templates/includes/path.html [deleted file]
panikweb_templates/templates/includes/piwik.html [deleted file]
panikweb_templates/templates/includes/player.html [deleted file]
panikweb_templates/templates/includes/related.html [deleted file]
panikweb_templates/templates/includes/topik.html [deleted file]
panikweb_templates/templates/includes/week-nav.html [deleted file]
panikweb_templates/templates/includes/week.html [deleted file]
panikweb_templates/templates/listen.html [deleted file]
panikweb_templates/templates/listen/archives.html [deleted file]
panikweb_templates/templates/listen/nav.html [deleted file]
panikweb_templates/templates/news.html [deleted file]
panikweb_templates/templates/news/archives.html [deleted file]
panikweb_templates/templates/news/inline.html [deleted file]
panikweb_templates/templates/news/nav.html [deleted file]
panikweb_templates/templates/news/roll.html [deleted file]
panikweb_templates/templates/news/search_result.html [deleted file]
panikweb_templates/templates/newsletter/confirmation_email_body.txt [deleted file]
panikweb_templates/templates/newsletter/confirmation_email_subject.txt [deleted file]
panikweb_templates/templates/newsletter/done.html [deleted file]
panikweb_templates/templates/newsletter/subscriber_form.html [deleted file]
panikweb_templates/templates/newsletter/thanks.html [deleted file]
panikweb_templates/templates/nonstop_playlist.html [deleted file]
panikweb_templates/templates/panikdb/base.html [deleted file]
panikweb_templates/templates/panikombo/audio.html [deleted file]
panikweb_templates/templates/panikombo/episode.html [deleted file]
panikweb_templates/templates/panikombo/episode_auto_selection.html [deleted file]
panikweb_templates/templates/panikombo/newsitem_auto_selection.html [deleted file]
panikweb_templates/templates/panikombo/topik-cell.html [deleted file]
panikweb_templates/templates/party.html [deleted file]
panikweb_templates/templates/program.html [deleted file]
panikweb_templates/templates/search/search.html [deleted file]
panikweb_templates/templates/soundfiles/dialog-embed.html [deleted file]
panikweb_templates/templates/soundfiles/embed.html [deleted file]
panikweb_templates/templates/soundfiles/resume.html [deleted file]
panikweb_templates/templates/tpl-default.html [deleted file]

index 44d48bb..9bcb2fc 100644 (file)
@@ -114,7 +114,7 @@ TEMPLATES = [
     {
         'BACKEND': 'django.template.backends.django.DjangoTemplates',
         'DIRS': [
-            os.path.join(PROJECT_DIR, 'panikweb_templates'),
+            os.path.join(PROJECT_DIR, 'panikweb', 'templates'),
         ],
         'APP_DIRS': True,
         'OPTIONS': {
@@ -156,7 +156,6 @@ INSTALLED_APPS = (
     'haystack',
     'taggit',
     'gadjo',
-    'panikweb_templates',
     'panikweb.paniktags',
     'sorl.thumbnail',
     'ckeditor',
diff --git a/panikweb/static/css/_general.scss b/panikweb/static/css/_general.scss
new file mode 100644 (file)
index 0000000..2632afa
--- /dev/null
@@ -0,0 +1,497 @@
+/******************/
+/*HTML TAG DISPLAYS */
+/******************/
+body {
+       font-family: "RegloNormal";
+       line-height: normal;
+       text-align: left;
+       margin:2.8em auto 0 auto;
+       /*padding: 0px 10px;*/
+       clear: both;
+}
+code,pre{
+       display:block;
+       overflow:auto;
+       padding:0.5em;
+       background:black !important;
+       color:white !important;
+       font-family:monospace;
+}
+audio { 
+       display:block;
+       width: 90%; 
+       margin:0.5em auto 1em auto;
+}
+
+a {
+       color:inherit;
+       text-decoration: none;
+}
+.userContent a:hover {
+    text-decoration: underline;
+}
+a.block:hover,nav a:hover{
+    text-decoration: none;
+}
+button, .button{
+       margin:0 0 0 0;
+       padding: 0 0 0 0;
+       cursor:pointer ;
+       background:none;
+}
+img {max-width:100%;}
+img.logo{border:2px solid black;}
+
+header{
+       padding:0 0 2em 0;
+       font-family: 'RegloBold';
+}
+h1, h2, h3, h4, h5{
+       font-family: 'RegloBold';
+       line-height:1em;
+       padding:0.2em 0 0.2em 0;
+}
+h1, h2, h3, h4{
+       text-transform: uppercase;
+}
+h1 {   font-size: 6em;}
+h2 {   font-size: 4em;}
+h3 {   font-size: 3em;}
+h4 {   font-size: 1.8em;}
+h5 {   font-size: 1.1em;}
+
+/*Specific rules for text writen by final users */
+.userContent h1 {      font-size: 2em;}
+.userContent h2  {     font-size: 1.9em;}
+h1, h2, h3, h4, .squashed{
+    font-family: 'RegloScale';
+    }
+
+nav{
+       padding:0em;
+       font-family: "RegloBold";
+       text-transform: uppercase;
+}
+hr {
+       height: 0;
+       margin:0.5em 0 0.5em 0;
+       padding:0;
+       border-style:solid;
+       border-width:2px 0 0 0 ;
+       border-color:black;
+}
+table{
+       margin:auto;
+       table-layout:fixed;
+}
+table,td,tr  {
+       padding:0;
+       margin:0;
+       word-wrap: break-word;
+       text-overflow: ellipsis;
+        text-align: center;
+        vertical-align: middle;
+        border: 1px solid #D0D0D0;
+       border-collapse:collapse;
+}
+th {
+       white-space: nowrap;
+       text-transform: uppercase;
+}
+tr{
+}
+p {
+    /*line-height: 1.2;*/
+    margin-bottom: 1em;
+}
+p  a {
+       text-decoration: underline
+}
+    
+em {
+    font-family: "RegloBold";
+    font-style: normal;
+}
+strong{
+       text-transform: uppercase;}
+blockquote {
+       padding: 1em;
+       font-style:italic;
+}
+
+dl{}
+dt, dd{        
+       letter-spacing:1px;
+       line-height: 150%;
+}
+dt {
+       float:left;
+       font-family: "RegloBold";
+       margin-right: 0.3em; 
+}
+dd {
+       font-family: "RegloNormal";
+}
+
+dt:after {
+    content: ":";
+}
+
+dl.metadata dt {
+       clear: none;
+       margin: 0;
+}
+
+dl.metadata dd {
+       margin-right: 4px;
+    }
+
+button {display:inline-block;}
+button {
+       font-family: "RegloBold";
+       text-transform: uppercase;
+}
+ul, ol, dl {
+       margin: 0;
+       padding: 0 0 0 2em;
+}
+nav ul, ul.inline, ul.custom, ul.custom li{
+       list-style: none;
+       margin: 0;
+       padding: 0;
+}
+nav ul li, ul.inline li{
+       display:inline;
+}
+ul.list{
+       list-style-type:square; /*Not working but why?*/
+       list-style-position:inside;
+}
+ul.list > li{
+       padding:0.5em 0 0.5em 0;
+       border-bottom:1px solid #ccc;
+}
+
+/******************/
+/*USEFULL CLASSES */
+/******************/
+
+.sr-only {
+       position: absolute !important;
+       width: 1px !important;
+       height: 1px !important;
+       padding: 0 !important;
+       margin: -1px !important;
+       overflow: hidden !important;
+       clip: rect(0, 0, 0, 0) !important;
+       white-space: nowrap !important;
+       border: 0 !important;
+}
+
+ul.distributed{
+       display:table;
+       width:100%;
+       text-align:center;
+       margin:0;
+       padding:0;
+       border-collapse:collapse;
+}
+ul.distributed li{
+       display:table-cell;
+       text-align:center;
+}
+ul.distributed.by2 li{
+       width:50%;
+}
+ul.distributed.by3 li{
+       width:33%;
+}
+ul.distributed.by4 li{
+       width:25%;
+}
+ul.distributed.by5 li{
+       width:20%;
+}
+ul.distributed.by6 li{
+       width:16.6666%;
+}
+ul.distributed.by7 li{
+       width:14.285%;
+}
+
+a.active, button.active{
+       font-weight:bold;
+       text-decoration:none;
+       border-bottom: 2px solid;
+}
+.active *{
+       font-weight:inherit;
+}
+
+.todo:hover, .todo *:hover{
+       text-decoration: line-through;
+       color:red !important;
+} 
+
+
+.focusFade {
+    -webkit-transition-property: color;
+    -webkit-transition-duration: 0.2s;
+    -webkit-transition-timing-function: ease;
+    }
+
+.extra-margin {
+    margin-bottom: 16px;
+}
+.ellipsis{
+   white-space: nowrap;
+   text-overflow: ellipsis;
+   overflow: hidden;
+}
+.block {display:block;}
+.inBlock{display:inline-block;}
+.right{float:right;margin-left:1em;}
+.left{float:left;margin-right:1em;}
+.userContent .right, .userContent .left{
+       margin-bottom:1.5em;
+}
+img.right, img.left{max-width:50%;}
+.smooth{opacity:0.5;}
+.hidden{display:none;}
+.invisible{visibility:hidden;}
+.padded{padding:1.5em;}
+.marged{margin:1.5em 0 1.5em 0;}
+    
+.small{        font-size: 80%;}
+.big{  font-size: 150%;}   
+.huge{ font-size: 200%;}
+
+.absolute{
+       position:absolute;
+}
+.relative{
+       position:relative;
+}
+.nowrap {
+       white-space: nowrap;
+}
+.center{
+       text-align:center;
+       margin-left:auto;
+       margin-right:auto;
+}
+
+.loading{
+   -webkit-animation: loading 1s infinite linear;
+   -moz-animation: loading 1s infinite linear;
+   -o-animation: loading 1s infinite linear;
+   animation: loading 1s infinite linear;
+}
+@-webkit-keyframes loading {0%{opacity:1 !important;}50%{opacity:0 !important;}100%{opacity:1 !important;}}
+@-moz-keyframes loading {0%{opacity:1 !important;}50%{opacity:0 !important;}100%{opacity:1 !important;}}
+@-o-keyframes loading {0%{opacity:1 !important;}50%{opacity:0 !important;}100%{opacity:1 !important;}}
+@keyframes loading {0%{opacity:1 !important;}50%{opacity:0 !important;}100%{opacity:1 !important;}}
+
+.spinning {
+   position:relative;
+   /*
+   -webkit-animation: rotation 10s infinite linear;
+   -moz-animation: rotation 10s infinite linear;
+   -o-animation: rotation 10s infinite linear;
+   animation: rotation 10s infinite linear;
+   */
+}
+@-webkit-keyframes rotation {
+   from {-webkit-transform: rotate(0deg);}
+   to {-webkit-transform: rotate(359deg);}
+}
+@-moz-keyframes rotation {
+   from {-moz-transform: rotate(0deg);}
+   to {-moz-transform: rotate(359deg);}
+}
+@-o-keyframes rotation {
+   from {-o-transform: rotate(0deg);}
+   to {-o-transform: rotate(359deg);}
+}
+@keyframes rotation {
+   from {transform: rotate(0deg);}
+   to {transform: rotate(359deg);}
+}
+.vertical {
+        -webkit-transform: rotate(-90deg);
+        -moz-transform: rotate(-90deg);
+        -ms-transform: rotate(-90deg);
+        -o-transform: rotate(-90deg);
+        filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
+}
+.columns{column-gap: 0;        -webkit-column-gap: 0;  -moz-column-gap: 0;}
+.columns.padded{column-gap: 2em;       -webkit-column-gap: 2em;        -moz-column-gap: 2em;}
+.columns li{
+       display:inline-block;
+       width:100%;
+       column-break-inside: avoid;
+       -moz-column-break-inside: avoid;
+       -webkit-column-break-inside: avoid;
+       break-inside: avoid-column;
+       -webkit-break-inside: avoid-column;
+       -moz-break-inside: avoid-column;
+}
+@media only screen and (min-width: 600px) {
+       .columns{column-count: 2;       -webkit-column-count: 2;        -moz-column-count: 2;}  
+}
+.columns.by3{column-count: 3;  -webkit-column-count: 3;        -moz-column-count: 3;}
+
+/* And the rest is Eric & Seb, AGPLv3*/
+
+label, select, input, button, textarea{
+       font-size:inherit;
+}
+label {
+       margin-right:1em;
+       height: 1.2em;
+       display: inline-block;
+       text-transform: uppercase;
+}
+
+select {
+    height: 1.2em;
+    -webkit-appearance: none;
+    -moz-appearance: window;
+}
+
+select[multiple],
+select[size] {
+    height: auto;
+    background-image: inherit;
+}
+
+input[type=date] {
+    -webkit-appearance: none;
+    -moz-appearance: window;
+}
+
+select, select option {
+    height: 1.2em;
+    text-transform: none;
+}
+
+input, select {
+    height: 1.2em;
+    background: #fff;
+    border: 1px inset #aaa;
+}
+
+
+input[type=text], textarea{
+       width: 100%; 
+       max-width:10em;
+       display: inline-block;
+       border:2px solid black;
+       border-radius:0.2em;
+       -moz-border-radius:0.2em;
+       -webkit-border-radius:0.2em;
+}
+
+input[type=submit] {
+    text-align: left;
+    border: none;
+}
+
+/**
+ * For modern browsers
+ * 1. The space content is one way to avoid an Opera bug when the
+ *    contenteditable attribute is included anywhere else in the document.
+ *    Otherwise it causes space to appear at the top and bottom of elements
+ *    that are clearfixed.
+ * 2. The use of `table` rather than `block` is only necessary if using
+ *    `:before` to contain the top-margins of child elements.
+ */
+.cf:before, .cf:after {
+    content: " "; /* 1 */
+    display: table; /* 2 */
+}
+
+.cf:after {
+    clear: both;
+}
+
+/**
+ * For IE 6/7 only
+ * Include this rule to trigger hasLayout and contain floats.
+ */
+.cf {
+    *zoom: 1;
+}
+
+/* icons */
+
+@font-face {
+        font-family: 'FontAwesome';
+        src: url('/static/xstatic/fonts/fontawesome-webfont.eot');
+        src: url('/static/xstatic/fonts/fontawesome-webfont.eot?#iefix') format('embedded-opentype'), url('/static/xstatic/fonts/fontawesome-webfont.woff') format('woff'), url('/static/xstatic/fonts/fontawesome-webfont.ttf') format('truetype'), url('/static/xstatic/fonts/fontawesome-webfont.svg#fontawesomeregular') format('svg');
+        font-weight: normal;
+        font-style: normal;
+}
+
+/* FONT AWESOME CORE
+ * -------------------------- */
+[class^="icon-"],
+[class*=" icon-"] {
+  font-family: FontAwesome;
+  font-weight: normal;
+  font-style: normal;
+  text-decoration: inherit;
+  -webkit-font-smoothing: antialiased;
+  *margin-right: .3em;
+}
+[class^="icon-"]:before,
+[class*=" icon-"]:before {
+  text-decoration: inherit;
+  display: inline-block;
+  speak: none;
+}
+/* makes sure icons active on rollover in links */
+a [class^="icon-"],
+a [class*=" icon-"] {
+  display: inline;
+}
+
+/* reglo symbols variants */
+[class^="icon-"].resymbol,
+[class*=" icon-"].resymbol {
+  font-family: Symbols;
+}
+
+/* specific icon classes */
+.icon-archive:before { content: "\f187"; }
+.icon-bolt:before { content: "\f0e7"; }
+.icon-bullhorn:before { content: "\f0a1"; }
+.icon-calendar:before { content: "\f073"; }
+.icon-check:before { content: "\f046"; }
+.icon-check-empty:before { content: "\f096"; }
+.icon-chevron-sign-left:before { content: "\f137"; }
+.icon-chevron-sign-right:before { content: "\f138"; }
+.icon-comments:before { content: "\f086"; }
+.icon-double-angle-left:before { content: "\f100"; }
+.icon-download:before { content: "\f01a"; }
+.icon-envelope:before { content: "\f0e0"; }
+.icon-file:before { content: "\f15b"; }
+.icon-globe:before { content: "\f0ac"; }
+.icon-headphones:before { content: "\f025"; }
+.icon-home:before { content: "\f015"; }
+.icon-info-sign:before { content: "\f05a"; }
+.icon-microphone:before { content: "\f130"; }
+.icon-pause:before { content: "\f04c"; }
+.icon-play:before { content: "\f04b"; }
+.icon-play-sign:before { content: "\f144"; }
+.icon-plus-sign:before { content: "\f055"; }
+.icon-question-sign:before { content: "\f059"; }
+.icon-remove:before { content: "\f00d"; }
+.icon-rss:before { content: "\f09e"; }
+.icon-search:before { content: "\f002"; }
+.icon-share:before { content: "\f045"; }
+.icon-step-backward:before { content: "\f048"; }
+.icon-step-forward:before { content: "\f051"; }
+.icon-stop:before { content: "\f04d"; }
+.icon-trash:before { content: "\f014"; }
+.icon-volume-up:before { content: "\f028"; }
diff --git a/panikweb/static/css/_grid.scss b/panikweb/static/css/_grid.scss
new file mode 100644 (file)
index 0000000..ce2f0de
--- /dev/null
@@ -0,0 +1,54 @@
+form.quixote div.grid {
+       float: left;
+       box-sizing: border-box;
+       padding-right: 1em;
+       clear: none;
+}
+
+@each $i in 1, 2, 3, 4, 6, 12 {
+       @for $j from 1 through $i {
+               div.cell.grid-#{$j}-#{$i},
+               div.dataview div.grid-#{$j}-#{$i},
+               form.quixote div.grid-#{$j}-#{$i} {
+                       clear: none;
+                       &.newline {
+                               clear: both;
+                       }
+               }
+               div.grid-#{$j}-#{$i} {
+                       float: left;
+                       box-sizing: border-box;
+                       padding-right: 1em;
+                       width: (100*$j/$i+0%);
+                       @media screen and (max-width: $mobile-limit) {
+                               @if $i == 4 and $j <= 2 { width: 50%; }
+                               @else if $i == 4 and $j >  2 { width: 100%; }
+                               @else if $i == 6 and $j <= 2 { width: (100/3+0%); }
+                               @else if $i == 6 and $j == 3 { width: 50%; }
+                               @else if $i == 6 and $j <= 5 { width: (200/3+0%); }
+                               @else if $i == 6 and $j == 6 { width: 100%; }
+                               @else if $i == 12 and $j <= 4 { width: (100/3+0%); }
+                               @else if $i == 12 and $j <= 7 { width: 50%; }
+                               @else if $i == 12 and $j <= 11 { width: (200/3+0%); }
+                               @else if $i == 12 and $j == 12 { width: 100%; }
+                       }
+                       @media screen and (max-width: $very-small-limit) {
+                               width: 100%;
+                       }
+                       textarea, select, input[type=text], input[type=password], input[type=email] {
+                               width: 100%;
+                       }
+               }
+               form div.grid-#{$j}-#{$i} + h3,
+               form div.grid-#{$j}-#{$i} + h4,
+               form div.grid-#{$j}-#{$i} + p,
+               form div.grid-#{$j}-#{$i} + div {
+                       clear: both;
+               }
+       }
+}
+
+form div[class*=grid-] span.select2-selection,
+form div[class*=grid-] div.select2-container {
+       width: 100% !important;
+}
diff --git a/panikweb/static/css/_reset.scss b/panikweb/static/css/_reset.scss
new file mode 100644 (file)
index 0000000..4cf6899
--- /dev/null
@@ -0,0 +1,206 @@
+/**
+ * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/)
+ * http://cssreset.com
+ */
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend, button,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+    margin: 0;
+    padding: 0;
+    border: 0;
+    font-size: 100%;
+    /*font: inherit;*/
+       color:inherit;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+    display: block;
+}
+body {
+    line-height: 1;
+}
+ol, ul {
+}
+blockquote, q {
+    quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+    content: '';
+    content: none;
+}
+table {
+    border-collapse: collapse;
+    border-spacing: 0;
+}
+
+h1, h2, h3, h5, h6 {
+    font-weight: normal;
+}
+button{background:none;border:none;}
+button:focus::-moz-focus-inner,
+button::-moz-focus-inner,
+input[type="reset"]::-moz-focus-inner,
+input[type="button"]::-moz-focus-inner,
+input[type="submit"]::-moz-focus-inner,
+input[type="file"] > input[type="button"]::-moz-focus-inner {
+  border: 0px dotted transparent;
+}
+/* The following code is taken from Normalize.css,
+ * available under the MIT License:
+ *
+ * Copyright (c) Nicolas Gallagher and Jonathan Neal
+ * 
+ * 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.
+ *
+ */
+
+// ==========================================================================
+// Forms
+// ==========================================================================
+
+//
+
+
+//
+// 1. Correct `color` not being inherited in IE 8/9.
+// 2. Remove padding so people aren't caught out if they zero out fieldsets.
+//
+
+legend {
+    border: 0; // 1
+    padding: 0; // 2
+}
+
+//
+// 1. Correct font family not being inherited in all browsers.
+// 2. Correct font size not being inherited in all browsers.
+// 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
+//
+
+button,
+input,
+select,
+textarea {
+    font-family: inherit; // 1
+    font-size: 100%; // 2
+    margin: 0; // 3
+    border: none;
+}
+
+//
+// Address Firefox 4+ setting `line-height` on `input` using `!important` in
+// the UA stylesheet.
+//
+
+button,
+input {
+    line-height: normal;
+}
+
+//
+// Address inconsistent `text-transform` inheritance for `button` and `select`.
+// All other form control elements do not inherit `text-transform` values.
+// Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
+// Correct `select` style inheritance in Firefox 4+ and Opera.
+//
+
+button,
+select {
+    text-transform: none;
+}
+
+//
+// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+//        and `video` controls.
+// 2. Correct inability to style clickable `input` types in iOS.
+// 3. Improve usability and consistency of cursor style between image-type
+//        `input` and others.
+//
+
+button,
+html input[type="button"], // 1
+input[type="reset"],
+input[type="submit"] {
+    -webkit-appearance: button; // 2
+    cursor: pointer; // 3
+}
+
+//
+// Re-set default cursor for disabled elements.
+//
+
+button[disabled],
+html input[disabled] {
+    cursor: default;
+}
+
+//
+// 1. Address box sizing set to `content-box` in IE 8/9.
+// 2. Remove excess padding in IE 8/9.
+//
+
+input[type="checkbox"],
+input[type="radio"] {
+    box-sizing: border-box; // 1
+    padding: 0; // 2
+}
+
+//
+// 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
+// 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
+//        (include `-moz` to future-proof).
+//
+
+input[type="search"] {
+    -webkit-appearance: textfield; // 1
+    -moz-box-sizing: content-box;
+    -webkit-box-sizing: content-box; // 2
+    box-sizing: content-box;
+}
+
+//
+// Remove inner padding and search cancel button in Safari 5 and Chrome
+// on OS X.
+//
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+    -webkit-appearance: none;
+}
+
+//
+// Remove inner padding and border in Firefox 4+.
+//
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+    border: 0;
+    padding: 0;
+}
+
+//
+// 1. Remove default vertical scrollbar in IE 8/9.
+// 2. Improve readability and alignment in all browsers.
+//
+
+textarea {
+    overflow: auto; // 1
+    vertical-align: top; // 2
+}
+
diff --git a/panikweb/static/css/_specifics.scss b/panikweb/static/css/_specifics.scss
new file mode 100644 (file)
index 0000000..cae6371
--- /dev/null
@@ -0,0 +1,2123 @@
+/* COLORS */
+
+$black: #000000;
+$white: #FFFFFF;
+$primary: #FF7E83;
+$secondary: #0062CB;
+
+/****************************************************/
+/* FONTS */
+
+.resymbol:hover,.control:hover{    opacity:0.5;    }
+.date, .dateBloc {
+       font-family: "Reglo";
+       text-transform: uppercase;
+}
+.inline .date, .resume .date{
+       text-align: center;
+}
+.dateBloc{width:4em;
+       text-align: center;}
+.dateBloc{display:inline-block;}
+.dateBloc *{line-height: 100%;}
+.dateBloc  .day {font-size: 1.8em;}
+.dateBloc .number {font-size: 1.8em;}
+.dateBloc  .month {font-size: 0.8em;}
+.dateBloc .time {font-size: 1.2em;margin: 0.2em 0;}
+
+.dateBloc.small{
+       font-size: 80%;
+}
+
+.date.smooth {
+       text-transform: none;
+       font-size: 100%;
+       font-family: RegloNormal;
+}
+
+.tabs .ui-tabs-nav {
+    font-family: "Reglo";
+    text-transform: uppercase;
+}
+.legend{
+       font-family: "Reglo";
+       font-size:1.2em;
+       border-bottom:3px solid black;
+       padding: 0.2em 0 0.2em 0;
+       margin: 0.2em 0 0.2em 0;
+}
+#Main .sectionLabel{
+       margin-bottom:1em;
+}
+
+.sectionLabel, .label {
+    text-transform: uppercase;
+    font-family: "Reglo";
+    font-size:1.3em;
+}
+
+.rightPart .right.sectionLabel {
+       text-transform: none;
+       border-bottom: 1px solid black;
+       padding-bottom: 3px;
+}
+
+h5.focus-title {
+       color: $secondary;
+}
+
+.rightPart #search-form {
+       text-align: right;
+       margin-bottom: 2em;
+}
+
+.label.relative{
+    background-color:black;
+    position: absolute;
+    left:10px;
+    top:-5px;
+    color:white;
+    padding:5px 7px 0px 7px;
+}
+
+/****************************************************/
+/* WRAPPER */
+/****************************************************/
+.wrapper {max-width: 1560px; padding:0 1%;}
+.wrapper.text {max-width: 780px; margin:auto;}
+.wrapper .rightPart{margin-top:1em;}
+
+@media screen and (min-width: 760px) {
+       #player-container.fixed {
+               position: fixed;
+               top: 60px;
+               width: calc(0% + 235px);
+       }
+       .wrapper .rightPart{
+        margin-top:0;
+       }
+       .wrapper.sided .leftPart,
+       .wrapper.sided .rightPart{
+               width:45%;
+       }
+       .wrapper.navigation .leftPart{
+               width:60%;
+       }
+       .wrapper.navigation .rightPart{
+               width:35%;
+       }
+       .wrapper .leftPart{
+               float:left;
+       }
+       .wrapper .rightPart{
+               float:right;
+       }
+       #specialHome {
+               padding-left: 0;
+       }
+    /*
+       #specialHome .leftPart,
+       #specialHome .rightPart {
+               width: 100%;
+       }
+    */
+       p.intro {
+               padding-top: 0px;
+               padding-bottom: 40px;
+       }
+}
+
+
+button.control, button.symbol{background:transparent;border:none;margin:0;padding:0;}
+nav.menu{
+       width:100%;
+       text-align: justify;
+       text-justify: distribute-all-lines;
+}
+nav.menu li{
+       display: inline-block;
+       margin-right:2em;
+}
+
+button.tag, a.tag{
+       font-size:0.9em;
+       background:white;
+       font-family: "RegloBold";
+       text-transform: uppercase;
+       display:inline-block;
+       border: 1px solid #CCC !important;
+       color:#342E2E;
+       margin: 0.2em;
+       padding: 0.3em;
+       border-radius: 0.7em;
+       -moz-border-radius: 0.7em;
+       -webkit-border-radius: 0.7em;
+}
+button.check, a.check {
+       font-size:0.9em;
+       text-transform: none;
+       display:inline-block;
+       margin: 0.2em;
+       padding: 0.3em;
+}
+
+.category{
+       font-family: "RegloBold";
+       text-transform: uppercase;
+}
+button.check:before, a.check:before {
+       display:inline-block;
+       width:1.5em;
+}
+.box{
+       padding:0.2em 0.5em 0.2em 0.5em;
+       border-radius: 0.2em;
+       -moz-border-radius: 0.2em;
+       -webkit-border-radius: 0.2em;
+       background:#222;
+       color:#fff;
+}
+.ui-tooltip {
+       border:1px solid white;
+       position:absolute;
+       margin:0;       
+       padding: 0.5em;
+       background:#222;
+       color: white;
+       z-index: 9999;
+       max-width: 50%;
+       background: white;
+       color: #222;
+       border-color: #222;
+}
+/****************************************************/
+/**** BODY ****/
+/****************************************************/
+body{
+       background: white;
+       color: #333;
+}
+/****************************************************/
+/**** metaNAV ****/
+/****************************************************/
+
+#metaNav {
+       color: #e8e8e8;
+       background-color: #3a3a3a;
+       position:fixed;
+       z-index:1000;
+       top:0px;
+       width:100%;
+       font-size: 90%;
+}
+#metaNav ul{
+}
+#metaNav ul li{
+       float: left;
+       padding: 0 1em;
+       white-space: nowrap;
+       text-overflow: ellipsis;
+       overflow:hidden;
+}
+
+#metaNav ul li#nav-search {
+       float: right;
+}
+
+#metaNav ul li a{
+       height: 3em;
+       line-height: 3em;
+       display:block;
+}
+
+#metaNav ul li#nav-language span {
+       cursor: pointer;
+       height: 3em;
+       line-height: 3em;
+       display: inline-block;
+}
+
+#metaNav ul li#nav-language span.lang-on {
+       color: white;
+}
+
+#metaNav ul li a span{
+       display:inline-block;
+}
+
+#metaNav ul li a span.nav-icon {
+}
+
+#metaNav a:focus, #metaNav a:hover{
+    opacity:0.8;
+}
+#metaNav ul li.active, #metaNav ul li.active a{
+       color: white;
+}
+
+#metaNav ul li.active span.iconLabel {
+}
+
+#metaNav li#nav-search a {
+       display: inline;
+}
+
+#metaNav form {
+       display: inline-block;
+       padding-top: 0.2em;
+}
+
+#metaNav input {
+       border: 1px solid #ececec;
+       width: 10em;
+}
+
+.icon-rss {
+       color: orange;
+}
+
+@media screen and (max-width:760px){
+       #bg-title { display: none; }
+       #metaNav .iconLabel {display:none;}
+       #metaNav ul li a span.nav-icon { display: inline-block; }
+       #metaNav ul li {
+               padding: 0;
+       }
+       #metaNav ul li a {
+               padding: 0 1em;
+       }
+       #metaNav form {
+               display: none;
+       }
+       #metaNav ul li#nav-language {
+               padding: 0.2em 0 0 1em;
+       }
+       div#Changing {
+               margin: 0 5px;
+       }
+}
+@media screen and (max-width:400px){
+       #metaNav ul li#nav-language {
+               padding: 0.2em 0 0 1ex;
+       }
+       #metaNav ul li a {
+               padding: 0 0.8em;
+       }
+}
+
+/****************************************************/
+/**** Commons ****/
+/****************************************************/
+
+.audio button {color:$primary !important;}
+/****************************************************/
+/**** HEADER ****/
+/****************************************************/
+
+/* PANIK LOGO */
+#Commons{
+       position: relative;
+       z-index: 5;
+}
+#Commons .wrapper{
+}
+#mainHeader {
+       padding-bottom:1em;
+}
+#mainHeader {
+    font-size:70%;
+}
+#mainHeader *{color:black !important;line-height:1em;}
+#mainHeader #radioPanik{}
+
+#Panik img{display:block;margin:auto;max-height:200px;}
+#mainHeader h1{
+       padding-left:75px;
+}
+#player-container #player{
+    padding:0 0 0 0;
+    min-width: 240px;
+}
+
+#Changing h1.top a:hover {
+       opacity: 1.0;
+}
+
+@media screen and (max-width: 760px) {
+       #All h1.top {
+               font-size: 60px;
+               padding: 0;
+               padding-top: 10px;
+               text-align: center;
+       }
+       #specialHome .leftPart h1.top {
+               display: none;
+       }
+       #specialHome .leftPart h2 {
+               padding-top: 10px;
+               text-align: center;
+       }
+}
+
+@media screen and (min-width: 760px) {
+       #Commons {
+               float: left;
+               width: 20%;
+               width: -webkit-calc(0% + 240px);
+               width: -moz-calc(0% + 240px);
+               width: calc(0% + 240px);
+       }
+       #Changing {
+               position: relative;
+               float: right;
+               width: 78%;
+               width: -webkit-calc(100% - 280px);
+               width: -moz-calc(100% - 280px);
+               width: calc(100% - 280px);
+       }
+       #All h1.top {
+               font-size: 120px;
+               font-family: RegloScale;
+               text-transform: uppercase;
+               padding-left: 0;
+               padding-top: 2rem;
+               padding-bottom: 0;
+       }
+
+       #metaNav {
+               padding-top: 2px;
+       }
+       #metaNav .nav-icon {
+               display: none !important;
+       }
+
+       ul#ticker {
+               margin-bottom: 10px;
+       }
+
+       #News div.mainSub,
+       #About div.mainSub,
+       #Emissions div.mainSub {
+               position: absolute;
+               top: 50px;
+               left: 320px;
+               width: 60%;
+               width: calc(98% - 320px);
+       }
+
+       #News div.mainSub ul,
+       #About div.mainSub ul,
+       #Emissions div.mainSub ul {
+               padding: 0;
+               font-family: Reglo;
+               font-weight: normal;
+       }
+
+       #News div.mainSub ul li,
+       #About div.mainSub ul li,
+       #Emissions div.mainSub ul li {
+       }
+
+       #News .news.wrapper {
+               padding: 0;
+       }
+
+       #News .news.wrapper li a {
+               margin-left: 0;
+               padding-left: 0;
+       }
+
+       #Nav header.marged,
+       #Main > .marged {
+               margin: 0;
+       }
+
+       #Related .wrapper,
+       #Main > .wrapper,
+       #Main > .soundfiles > .wrapper,
+       #Main > .news > .wrapper,
+       #Nav > .wrapper {
+               padding-left: 0;
+       }
+
+       #All #Nav nav ul {
+               margin-top: 0;
+       }
+
+       #Related .padded,
+       div.program.padded {
+               padding-top: 0;
+               padding-left: 0;
+       }
+
+       div.program.padded {
+               padding-top: 1.5em;
+       }
+
+       #fiber-content h2.title {
+               margin-top: 0;
+               padding-top: 0;
+       }
+
+}
+
+#backgroundBox {
+       background: transparent center 40px no-repeat url(../img/Radio_Panik_Logo_2016-01.png);
+}
+
+#All #backgroundBox h1.top {
+       font-size: 50px;
+       padding-left: 10px;
+       width: 200%;
+}
+
+#backgroundBox h1 {
+       color: $primary !important;
+}
+
+#All h1.top#radiopanik {
+       padding-top: 0;
+       color: black !important;
+       padding-bottom: 30px;
+        height: 130px;
+}
+
+#All #backgroundBox h1 {
+       visibility: hidden;
+}
+
+
+#specialHome div.rightPart h1,
+div.focus {
+       color: $secondary;
+}
+
+h1.top#frequence {
+       color: $primary;
+}
+
+/****************************************************/
+/****  SCREEN NAV ****/
+#Nav nav{padding:0.1em;}
+
+#Nav input{color:#333;}
+#Nav ul li button,
+#Nav ul li a {
+       border-width:0 0 2px 0;
+       border-style: solid;
+       border-color: transparent;
+}
+
+#Nav .current,
+#Nav .active,#Nav .icon-check,#Nav .active *{
+       font-weight: normal;
+}
+
+#Nav .selected a,
+#Nav ul li.current a, #Nav ul a.active, #Nav button.active {
+       border-color: #333;
+}
+
+#Nav nav{
+       margin:0;
+}
+
+#specialHome h2,
+#Nav h2{
+       margin:0;
+       padding:0;
+}
+#Nav nav ul{
+       margin:1em 0 1em 0;
+}
+
+#Nav li {
+       padding-right: 1em;
+}
+
+#Nav li a{
+       display: inline-block;
+}
+#Nav nav ul.distributed li {padding: 0;}
+
+#fiber-nav{
+    font-size:150%;
+       border-width:0 0 2px 0;border-style:solid;
+}
+#fiber-nav li, #fiber-nav li a{
+       display:block;
+}
+#fiber-nav ul{
+       padding:0.5em;
+}
+#fiber-nav li a{
+       padding:0.5em;
+}
+#fiber-nav .selected > a,
+#fiber-nav .current {
+    font-weight:bold;
+}
+
+/****************************************************/
+/**** PLAYER ****/
+/****************************************************/
+/*#Home #player{   float: left; } */
+
+#player-container,
+   #player-container *{border-color:$primary !important;color:$primary !important;}
+
+#player-container .metas, #player-container img{border-color:#fff;}
+#player-container .padded{padding:0.3em;}
+
+#player-container button,#player-container a{
+}
+#player-container .metas{
+    float:right;
+}
+#DirectStreamPanikControler {
+       display:inline !important;
+}
+#chatSymbol,
+#streamSymbol{
+       font-size:3em;
+       float:left;
+       margin-right:5px;
+       position: relative;
+       z-index: 10;
+       top: -6px;
+}
+#CurrentlyPlaying{
+       padding:0 0 0 0;
+}
+
+#Player.withPlaylist #player-container #Playlist{
+       border-top:2px solid black;
+}
+#Player.withPlaylist #player-container #Playlist{
+       margin-top: 1em;
+       padding-top: 1em;
+}
+
+#player-container #myPlaylist {
+       clear: both;
+       padding: 1em 0 0 0;
+       height: auto;
+}
+
+#player-container #myPlaylist a {
+       margin-right: 30px;
+       white-space: normal;
+       padding-bottom: 1ex;
+}
+
+#player-container.minimized{
+       width:auto;
+       border-width:0px 2px 2px 0 !important;
+       border-bottom-right-radius:1em;
+       -moz-border-bottom-right-radius:1em;
+       -webkit-border-bottom-right-radius:1em;
+}
+#player-container.minimized #player{
+       padding:0;
+}
+
+/*Playlist*/
+
+#Playlist #playlistLabel{
+       float:right;
+
+}
+#Playlist .playListControls{   
+}
+#Playlist .playListControls button{    
+       margin-right:0.5em;
+       display:inline-block;
+}
+#Playlist .playListControls .playPause{
+       font-size:3em;
+       margin-right:5px;
+       float:left;
+       position: relative;
+       top: -8px;
+}
+
+#Playlist .playing .icon-pause{
+   -webkit-animation: loading 1s infinite linear;
+   -moz-animation: loading 1s infinite linear;
+   -o-animation: loading 1s infinite linear;
+   animation: loading 1s infinite linear;
+}
+#Playlist .playlistControls button,#Playlist .playlistControls .button{
+       margin:0 0.1em 0 0.1em;
+}
+#Playlist li{
+       clear:right;
+}
+#Playlist .soundControls button{}
+
+#player-container #Playlist ol{
+       clear:right;
+       padding:0;
+       margin-left: 50px;
+}
+#player-container #Playlist ol li{
+       line-height:1.3em;
+       padding:0;
+       margin:0;
+}
+#Playlist ol li .soundControls{
+       line-height:1.5em;
+       height:1.5em;
+       clear:right;
+       float:right;
+}
+#Playlist ol li .title{
+       margin-right:70px;
+       display:block;
+       white-space: nowrap;
+       text-overflow: ellipsis;
+       overflow: hidden;
+}
+#player .active{
+       text-transform:uppercase;
+       font-weight:bold;
+}
+/*limit height of playlist*/
+#player #CurrentlyPlaying,
+ #player-container #Playlist ol{
+       opacity:0.9;
+       padding-top:0.2em;
+       height:auto;
+       overflow: hidden;
+}
+
+@media screen and (max-width: 760px) {
+        #backgroundBox {
+                background-position: center 30px;
+                background-size: 130px;
+        }
+        #All h1.top#radiopanik {
+                height: 80px;
+        }
+       #Player{
+        margin-top:1em;
+    }
+       #Player.withPlaylist #player-container #audioPlayer,
+         #Player.withPlaylist #player-container #audioPlayer,
+          #Player.withPlaylist #player-container #Playlist{
+               float:none !important;
+               width:auto !important;
+        border-right:none !important;
+               max-width:auto !important;
+       }
+
+       #player.on-chat-page {
+               display: none;
+       }
+
+       div.chat-page .rightPart {
+               font-size: 95%;
+               margin-top: 4em;
+               padding-top: 1em;
+               border-top: 1px solid #777;
+       }
+
+}
+
+/****************************************************/
+/**** #Changing #Footer ... ****/
+/****************************************************/
+#Changing{
+       display: flex;
+       flex-direction: column;
+       min-height: 97vh;
+}
+
+#Main{
+       flex-grow: 1;
+       color:#333;
+       position: relative;
+       z-index: 1;
+}
+#Main >.wrapper{
+       padding-bottom:2em;
+}
+#Home #Main{
+       min-height:0;
+}
+#Changing a:hover,#Changing button:hover {
+       opacity:0.6;
+       text-decoration:none;
+}
+/* GLOBAL SITE NAV */
+#userLog{
+       z-index:2000;
+       position: fixed;
+       bottom: 0px;
+       right: 0px;
+}
+#userLog .log{
+       margin:0.3em;
+       -moz-box-shadow: 0px 0px 3px #000;
+       -webkit-box-shadow: 0px 0px 3px #000;
+       box-shadow: 0px 0px 3px #000;
+       border-radius:0.5em;-moz-border-radius:0.5em;-webkit-border-radius:0.5em;
+       text-align:center;
+       padding: 0.3em;
+       font-size:0.9em;
+       color:black;
+       background-color:$primary;
+       border: 2px solid black;
+       background-image: linear-gradient(135deg, rgba(0, 0, 0, 0.04) 25%, transparent 25%, transparent 50%, rgba(0, 0, 0, 0.04) 50%, rgba(0, 0, 0, 0.04) 75%, transparent 75%, transparent);
+}
+#userLog .log.info{
+       background-color:grey;
+       color:white;
+}
+#userLog .log.ok{
+       background-color:green;
+       border-color:black;
+       color:white;
+}
+#userLog .log.error{
+       background-color:$primary;
+       border-color:yellow;
+}
+#main {}
+#mainLegend{
+       width:30%;
+       text-align:right;
+       float:right;
+       padding:1em;
+}
+
+#Footer{
+       border-top:2px solid #333;
+       padding-top: 2em;
+       padding-bottom: 80px;
+       position: relative;
+       z-index: 3;
+}
+
+#Footer ul {
+}
+
+#Footer ul li {
+       padding-right: 2em;
+}
+
+#Footer a:hover {
+       opacity:0.6;
+}
+
+
+/****************************************************/
+.inline .link{display:block;padding:1em;}
+/**** Liste   ****/
+/**** EMISSIONS ****/
+#Emission .emission-detail .title{}
+/*
+*/
+#Emission-tabs-menu .sub{
+       margin-bottom:1em;
+}
+/**** Detail   ****/
+.emission-detail .metas{
+       line-height:1.5em;
+       float: left;
+       width: 49%;
+       margin-top: 0;
+}
+
+.emission-detail h4.subtitle {
+       margin-top: 1em;
+       font-weight: normal;
+       font-family: 'Reglo';
+       text-transform: none;
+       float: left;
+}
+
+.emission-detail ul.schedule {
+       margin-top: 0;
+       margin-bottom: 1em;
+ }
+
+.emission-detail ul.schedule .weekdiff {
+       font-size: 80%;
+}
+
+.emission-detail article {
+       clear: both;
+}
+
+.emission-detail .logo{
+       float:right;
+       width: 50%;
+       margin-bottom: 1ex;
+}
+@media screen and (max-width: 300px) {
+       .emission-detail .metas {
+               float: none;
+               width: auto;
+               margin: 0;
+       }
+       .emission-detail .logo{max-width:100%;}
+}
+.emission .mainHeader {
+    overflow: hidden;
+    margin-bottom:1.5em;
+}
+
+.emission .contacts {
+       clear: both;
+}
+
+/**** Inline   ****/
+.emission.inline, .emission.resume {
+       padding:1em 0 1em 0;
+}
+
+.emission.inline div.date {
+       min-height: 3em;
+       text-align: center;
+       display:inline-block;
+       float:left;
+       margin-right:1em;
+}
+.emission .archived {
+       opacity:0.6;
+}
+
+.emission .link .description {
+       margin: 0px 0 5px 0;
+       font-family: "RegloMedium";
+}
+
+
+/**** EPISODE ****/
+/**** Detail  ****/
+
+.episode .tag{
+}
+.episode.resume, .episode.inline{
+       padding:1em 0.5em 1em;
+}
+.episode.inline .dateBloc, .episode.resume .dateBloc{
+       float:left;
+}
+.episode.resume img {
+       border: 2px solid black;
+}
+
+.episode.resume .title{
+       margin-bottom:0.5em;
+}
+.episode.resume .logo{
+       float: right;
+}
+.topik-link .logo,
+.episode.inline .logo {
+       min-height: 50px;
+       float: left;
+       margin-right: 1em;
+}
+.episode.resume .sound{
+       float:right;
+       margin:0 0 0.5em 0.5em;
+}
+.episode.inline .sound.right{
+       text-align:center;
+       font-size:70%;
+       position: relative;
+       z-index: 10;
+}
+.episode.inline .sound.right button{
+    font-size:1.5em;
+       display:inline;
+       text-align:center;
+       padding-bottom:0.05em;
+}
+.episode.resume .sound.right .icon-download{
+       text-align:center;
+}
+.episode.resume .sound.right .icon-download{
+       display:block;
+}
+
+.big.icon-pause,
+.big.icon-stop,
+.big.icon-share {
+       display: inline-block;
+       vertical-align: middle;
+}
+
+.episode.detail .logo.right{
+       max-width:50%;
+}
+
+.episode.resume .date .day, .emission-detail .date .day {
+}
+
+.episode.resume .content {
+       padding-left: 5em;
+}
+.episode.resume .content .title {
+}
+
+.episode.resume .logo {
+       margin:0 0 1em;
+       max-width:20%;
+}
+.episode.inline .date{
+       font-size:80%;
+}
+
+#Emission-tabs-menu .emissions-newsitems {
+       margin-bottom: 2em;
+}
+
+#Emission-tabs-menu .emissions-newsitems ul.list li {
+       border: 0;
+}
+
+#Emission-tabs-menu .futur-episodes h5,
+#Emission-tabs-menu .recent-episodes h5 {
+       font-size: 1.2em;
+}
+
+#Emission-tabs-menu #search-form {
+       margin-bottom: 1em;
+}
+
+div.extra-soundfiles h3 {
+       margin-top: 1em;
+       font-size: 2.5em;
+}
+
+div.extra-soundfiles ul li {
+       position: relative;
+}
+
+div.extra-soundfiles ul li div.audio {
+       display: inline;
+       top: 5px;
+       right: 0;
+       position: absolute;
+       font-size: 60%;
+}
+
+div.extra-soundfiles ul strong {
+       padding-right: 3em;
+}
+
+@media screen and (max-width: 400px) { 
+       .episode .dateBloc{
+               width:4em;
+               font-size:80%
+       }
+
+       .episode.resume .content {
+               padding-left: 4em;
+       }
+}
+
+/****************************************************/
+/**** News ****/
+
+#newsRoll {
+       max-width: 500px;
+}
+
+#newsRoll li {
+       background: white;
+}
+
+.newsRoll .title{
+       background:black;
+       color:white;
+       bottom:0px;
+       opacity:0.9;
+    width:100%;
+       text-align: left;
+       font-family: "RegloBold";
+       position: absolute;
+       left: 0;
+}
+.newsRoll .title div{
+       padding: 1em;
+}
+.newsRoll a, .newsRoll button img{
+    border:3px solid $secondary;
+}
+
+.newsRoll .by3 button {
+       width: 100%;
+}
+
+.soundfiles .special a,
+.news .special a {
+       position: relative;
+}
+
+.special .labels .item,
+.newsRoll .labels .item{
+       display:block;
+       background: $secondary;
+       color:white;
+       margin:0.1em;
+       font-size:0.9em;
+       padding:0.3em;
+}
+.newsList .current a{
+    opacity:0.5;
+}
+/****************************************************/
+.list.news li {
+}
+
+.soundfiles ul.custom li a,
+.news ul.custom li a { max-width: 98%; }
+.news li.item a {padding:1em;}
+
+.logo img{
+       display:block;
+       border-style:solid;
+       border-width:3px;
+}
+ul.newsSpecial{
+       border-bottom:3px solid #ccc;
+}
+@media only screen and (max-width: 970px) {
+       .columns {column-count: 1;      -webkit-column-count: 1;        -moz-column-count: 1;}
+}
+
+
+/****************************************************/
+/**** Home & ****/
+/****************************************************/
+
+#Home #Nav .wrapper{
+       max-width:auto !important;
+       width:auto !important;
+}
+
+/*
+@media screen and (max-width:800px){
+       #Home .newsRoll .logo{
+               max-width:100px;
+       }
+}
+@media screen and (max-width:600px){
+       #Home .newsRoll .logo{
+               max-width:50px;
+       }
+}
+*/
+
+/****************************************************/
+/**** PROGRAM ****/
+/****************************************************/
+
+.program.tabs nav ul li{
+       display:table-cell;
+       width:14%;
+       text-align:center;
+}
+
+.program.tabs nav ul li.week-arrow {
+       width: 1%;
+       padding-bottom: 5px;
+}
+
+.program ul .dateBloc {
+       float:left;
+       padding-top:1em;
+}
+.program ul .schedule {
+       margin-left:5em;
+}
+.program .nonstop {
+       text-align:left;
+}
+.program-week .programDate{
+       float:left;
+       width:3em;
+}
+.program-week .programCell{
+       margin-left:3.5em;
+}
+.program-week .nonStop .programDate{
+       visibility:hidden;
+}
+.program-week .nonStop .programCell{
+       font-size:0.9em;
+       padding-left:50%;
+       text-align:right;
+}
+.program-week a.nonstop{
+       font-size:0.9em;
+       margin:0.1em;
+}
+.program-week .inline,.program-week .resume{padding:0;}
+.program-week .description{}
+
+.program-week .title {
+       color: black;
+       display: inline;
+}
+
+.program-week .smooth {
+       color: #666;
+       opacity: 1.0;
+       font-size: 80%;
+       padding-bottom: 8px;
+}
+
+.program-week .emission h5,
+.program-week .smooth .title {
+       color: #333;
+       text-transform: uppercase;
+}
+
+.program-week .description {
+       color: black;
+       font-size: 90%;
+}
+
+.program-week .programCell:hover {
+       opacity: 0.5;
+}
+
+#Changing .program-week .programCell a {
+       opacity: 1.0;
+}
+
+#Changing .program-week .programCell .smooth a {
+       opacity: 0.5;
+}
+
+#Changing .program-week .programCell .smooth h5 a {
+       opacity: 1.0;
+}
+
+
+/****************************************************/
+/**** SEARCH ****/
+/****************************************************/
+
+.search li.previous-page {
+  margin-bottom: 2ex;
+  text-align: left;
+  margin-left: 0ex;
+  font-style: italic;
+}
+
+.search li.next-page {
+  margin-top: 2ex;
+  text-align: right;
+  margin-right: 0;
+  font-style: italic;
+}
+
+.search-filters {
+  text-align: justify;
+}
+
+
+/****************************************************/
+/**** GRILLE ****/
+/****************************************************/
+
+#grid #Main {}
+#grid th{
+       color:#000;
+}
+#grid .heure {
+       height:50px !important;
+}
+#grid .heure.vertical {
+       padding:1.5em 0;
+}
+#grid .day {
+       padding:1em 0 1em 0;
+}
+#grid .nonstop {
+}
+#grid .item{
+       padding:0.5em 0.2em 0.5em 0.2em;
+}
+#grid .cell hr {
+       border:1px dotted #ddd;
+       margin:0.3em;
+}
+#grid .time-label{
+       margin-top:0.5em;
+}
+
+#grid .highlighted,#grid .highlighted  *{
+       background:#333 !important;
+       color:white !important;
+}
+
+#grid .highlighted,#grid .highlighted  *{
+       background:#333 !important;
+       color:white !important;
+}
+#Emissions li.item.normal{
+       display:none;
+}
+#Emissions li.item.hightlighted{
+       display:block !important;
+}
+
+#gridNav span.category {
+       text-transform: none;
+}
+
+
+/**** Navigation for static pages ****/
+
+#fiber-nav {
+       font-size: 150%;
+}
+#fiber-nav li, #fiber-nav li a {
+       display: block;
+}
+#fiber-nav ul{
+       padding: 0.5em;
+}
+#fiber-nav li a{
+       padding:0.5em;
+}
+
+#fiber-content a {
+       text-decoration: underline;
+}
+
+#fiber-content .episode a,
+#fiber-content ul.list a {
+       text-decoration: none;
+}
+
+#fiber-content a:hover {
+       text-decoration: none;
+}
+
+.intro,
+.userContent,
+#fiber-content,
+.content,
+.content h5 {
+       line-height: 120%;
+}
+
+.userContent strong,
+#fiber-content strong {
+       text-transform: none;
+       font-family: "RegloBold";
+       font-style: normal;
+}
+
+.userContent em,
+#fiber-content em {
+       font-family: inherit;
+       font-style: italic;
+}
+
+/**** SCREEN SIZE ADAPTATIONS ****/
+    html #main{ font-size: 70%; }
+body { font-size: 18px;}
+@media (max-width: 300px){
+    body #All{ font-size: 80%; }
+}
+
+@media (min-width: 300px) and (max-width:800px){
+    body #All{ font-size: 85%; }
+}
+
+@media (min-width: 700px) and (max-width:1000px){
+    body #All{ font-size: 90%; }
+}
+
+@media (min-width: 1000px) {
+    body #All{ font-size: 100%; }
+}
+
+#subscribe-form {
+  position: relative;
+  margin-bottom: 2em;
+  padding-bottom: 2em;
+}
+
+#Home #subscribe-form {
+  margin-bottom: 0;
+}
+
+#subscribe-form ul.errorlist {
+  position: absolute;
+  bottom: -2em;
+  text-align: center;
+  display: block;
+  width: 100%;
+  padding: 0;
+  list-style: none;
+  color: #800;
+}
+
+#subscribe-form input {
+       width: 15em;
+       max-width: none;
+}
+
+#Nav div.search form {
+  padding: 1em 0;
+}
+
+div.episode.resume div.title {
+       white-space: normal;
+}
+
+#Home div.program.tabs {
+       margin: 1em 0;
+}
+
+nav#program li {
+       display: block;
+       margin: 0;
+}
+
+#recent-emissions,
+#recent-news,
+#recent-sounds {
+       margin-top: 2em;
+}
+
+#recent-emissions h3,
+#recent-news h3,
+#recent-sounds h3 {
+       font-size: 140%;
+}
+
+#recent-emissions h3.sectionLabel {
+       margin-bottom: 0;
+}
+
+.episode.soundfile {
+       padding: 0;
+}
+
+.soundfile .smooth {
+       color: #666;
+       opacity: 1.0;
+       font-size: 80%;
+}
+
+
+.soundfile p.date {
+       margin: 0;
+}
+
+.frontpage.soundfile .audio {
+       font-size: 80%;
+       padding-top: 0.5ex;
+       padding-bottom: 1ex;
+}
+
+#panikdb {
+       position: absolute;
+       top: -20px;
+       right: 0px;
+       background: white;
+       color: #888;
+       padding: 5px 10px;
+       border: 1px solid #888;
+       border-width: 1px 1px 0 1px;
+       -webkit-transform-origin: bottom right;
+       -webkit-transform: rotate(270deg);
+       -moz-transform-origin: bottom right;
+       -moz-transform: rotate(270deg);
+       transform-origin: bottom right;
+       transform: rotate(270deg);
+}
+
+img.logo.right {
+       margin-bottom: 1em;
+}
+
+.soundfile .special,
+.newsitem .special {
+       margin-bottom: 2em;
+}
+
+.newsitem .special .smooth {
+       padding-top: 5px;
+}
+
+/* USER CONTENT */
+
+div.userContent ul {
+       margin: 1em 0;
+}
+
+div.userContent h1,
+div.userContent h2,
+div.userContent h3,
+div.userContent h4 {
+       text-transform: none;
+       font-family: "Reglo";
+       font-weight: normal;
+}
+
+div.userContent h1 { font-size: 2em; }
+div.userContent h2 { font-size: 1.8em; }
+div.userContent h3 { font-size: 1.5em; }
+div.userContent h4 { font-size: 1.5em; }
+div.userContent a { text-decoration: underline; }
+
+div.userContent a.tag { text-decoration: none; }
+
+@media screen and (max-width: 760px) {
+       #streamSymbol{
+               top: 0;
+       }
+       #MainHeader {
+               margin: 0 auto;
+       }
+       #All #backgroundBox h1.top {
+               width: 94%;
+       }
+
+       #Player.withoutPlaylist #player-container #audioPlayer{
+           margin:auto;
+           width:100%;
+       }
+       #Player.withoutPlaylist #player-container #audioPlayer #Live{
+           font-size:150%;
+       }
+
+
+       #player-container { width:100%;left:0;border-width: 2px 0 0 0;border-style:solid;}
+       #player-container{
+               background: $primary;
+       }
+        #player-container * {color: white !important; }
+       #player-container{
+               z-index:500;
+               position:fixed;
+               width:100% !important;
+               /*top:2em;*/
+               font-size:80%;
+               bottom:0em;
+               border-bottom:none;
+       }
+       #Player.withPlaylist #player-container #audioPlayer{
+               float:left;
+               width:50%;
+               border-right:2px solid black;
+       }
+       #Player.withPlaylist #player-container #Playlist{
+               float:right;
+               width:49%;
+               text-align:left;
+       }
+       #player-container #myPlaylist {
+               padding: 0;
+       }
+
+       #player-container #myPlaylist a {
+               white-space: nowrap;
+       }
+
+       #player-container #Playlist ol{
+               margin-left: 30px;
+       }
+}
+
+div.emission-logo {
+       margin-left: 1em;
+}
+
+div.extra-soundfiles {
+       clear: both;
+}
+
+h3.episode-subtitle {
+       font-size: 2.5em;
+}
+
+.waveform {
+       display: none;
+       position: relative;
+}
+
+.waveform span {
+       background: #3A3A3A;
+       background: rgba(10, 10, 10, 0.8);
+       display: inline-block;
+       width: 0.50%;
+}
+
+.waveform span.done {
+       background: linear-gradient(to top, #3A3A3A 0%, #858585 80%);
+}
+
+.waveform span.done.current + span {
+       background: $primary;
+}
+
+.waveform i.duration {
+       position: absolute;
+       right: 4px;
+       bottom: 4px;
+       color: $primary;
+       text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
+       font-style: normal;
+       font-weight: bold;
+}
+
+span.timestamp {
+       cursor: pointer;
+       border-bottom: 1px dotted #666;
+}
+
+div.fragment-sound {
+       position: relative;
+}
+
+div.soundcell div.logo {
+       vertical-align: top;
+}
+
+div.fragment-sound {
+}
+
+div.extra-soundfiles div.fragment-sound {
+       margin-top: 5px;
+}
+
+div.extra-soundfiles div.fragment-name {
+       font-style: italic;
+       position: relative;
+       top: 1ex;
+       max-width: 70%;
+}
+
+div.extra-soundfiles ul li div.fragment-sound div.waveform {
+}
+div.extra-soundfiles ul li div.fragment-sound div.audio {
+       bottom: 0;
+}
+
+#fiber-content div.extra-soundfiles strong {
+       text-transform: uppercase;
+
+}
+
+.nonstop-track-title, .nonstop-track-artist {
+       font-size: 80%;
+}
+
+.soundfile-info {
+        padding-right: 75px;
+}
+
+#fiber-content div.extra-soundfiles .soundfile-info strong {
+        padding-right: 0;
+}
+
+#fiber-content div.extra-soundfiles .soundfile-info a {
+        text-decoration: none;
+}
+
+#fiber-content div.extra-soundfiles {
+       margin: 1em 0;
+}
+
+div.extra-soundfiles div.logo {
+       display: inline-block;
+}
+
+div#fiber-content div.extra-soundfiles ul.list {
+       display: inline-block;
+       width: 88%;
+       width: calc(100% - 74px);
+}
+
+div.download-links {
+       position: absolute;
+       z-index: 1000;
+       text-align: right;
+}
+
+div.hidden-download-links {
+       display: none !important;
+}
+
+div.episode-detail div.sound div.download-links {
+       display: inline-block;
+       padding-top: 1ex;
+       padding-left: 3em;
+}
+
+div.extra-soundfiles div.download-links {
+       background: white;
+}
+
+h1.top a.dimmed {
+       opacity: 0.7;
+}
+
+div#agenda div.content-inline {
+       margin-bottom: 1em;
+}
+
+div.previous-and-next-months {
+       margin-top: 1em;
+}
+
+div.publication-date.date.smooth {
+       font-size: 80%;
+}
+
+#All h1.top.fullwidth {
+       width: 150%;
+}
+
+div.gallery img {
+       padding: 2px;
+       background: white;
+       border: 1px solid #333;
+}
+
+div#dialog-background,
+div.gallery div.first {
+       position: fixed;
+       top: 0;
+       left: 0;
+       width: 100%;
+       height: 100%;
+       background: rgba(0, 0, 0, 0.9);
+       z-index: 1000;
+       text-align: center;
+}
+
+div.gallery div.first img {
+       padding: 5px;
+       padding-bottom: 25px;
+       margin-top: -240px;
+       margin-left: -320px;
+       position: absolute;
+       top: 50%;
+       left: 50%;
+       transition: all 0.5s ease;
+       transform-origin: bottom left;
+}
+
+div.portrait div.gallery div.first img {
+       margin-top: -320px;
+       margin-left: -240px;
+}
+
+div.gallery {
+       border-bottom: 1px solid #ccc;
+}
+
+div.gallery span.gallery-legend {
+       display: inline-block;
+       position: absolute;
+       top: 50%;
+       margin-top: 250px;
+       left: 0%;
+       width: 100%;
+       color: #000;
+       z-index: 1000;
+}
+
+div.portrait div.gallery span.gallery-legend {
+       margin-top: 330px;
+}
+
+div.gallery span.image {
+       display: inline-block;
+       cursor: pointer;
+}
+
+@media screen and (max-width: 640px) {
+       div.portrait div.gallery div.first img,
+       div.gallery div.first img {
+               max-width: 80vw;
+               margin: 0;
+               max-height: 80vh;
+               left: 10vw;
+               top: 10vh;
+               display: inline-block;
+       }
+}
+
+ul.tags {
+       padding-top: 1em;
+       clear: both;
+}
+
+a.topik-link {
+       clear: both;
+       display: block;
+       margin-top: 1em;
+}
+
+#fiber-content div.topikcellcontent a {
+       text-decoration: none;
+       height: 500px;
+}
+
+#fiber-content div.cell.topik-large a {
+       height: auto;
+}
+
+div.topikcellcontent h5 {
+       padding-top: 1ex;
+}
+
+div.topik-large div.topikcellcontent a {
+       width: 100%;
+       float: none;
+       display: inline-block;
+       text-align: left;
+}
+
+div.topik-large div.topikcellcontent img {
+       width: 100%;
+       display: block;
+}
+
+div.topik-large div.topikcellcontent a div {
+       @media screen and (min-width: 760px) {
+               display: flex;
+       }
+       margin-top: 1ex;
+       h2 {
+               margin-top: 0;
+               white-space: nowrap;
+               margin-right: 1ex;
+               @media screen and (max-width: 760px) {
+                       padding-bottom: 0;
+               }
+       }
+}
+
+div.topikcellcontent a {
+       margin-bottom: 2em;
+       display: inline-block;
+       text-align: left;
+       width: 50%;
+       box-sizing: border-box;
+       padding-right: 2em;
+       float: left;
+}
+
+div.topikcellcontent img {
+}
+
+div.topikcellcontent h2 {
+       font-size: 3.5em;
+}
+
+@media only screen and (min-width: 1250px) {
+       div.topikcellcontent a {
+               display: inline-block;
+               text-align: left;
+               width: 50%;
+               float: left;
+       }
+}
+
+.program-week img.smooth {
+       padding-bottom: 0;
+}
+
+div#dialog-background {
+       display: flex;
+}
+div#dialog-embed {
+       position: relative;
+       background: white;
+       width: 50%;
+       margin: auto;
+       text-align: left;
+       padding: 1ex;
+}
+
+div#dialog-embed textarea {
+       width: 100%;
+       max-width: none;
+}
+
+div#dialog-embed #close-button {
+       position: absolute;
+       right: 1ex;
+}
+
+body#embed {
+       min-height: auto !important;
+       margin: 0;
+       background: white;
+}
+
+body#embed #Main {
+       background: transparent;
+}
+
+body#embed #Commons,
+body#embed #metaNav,
+body#embed #Footer,
+body#embed #userLog,
+body#embed #panikdb,
+body#embed #Player {
+       display: none;
+}
+
+body#embed #Changing {
+       float: none;
+       width: auto;
+}
+
+body#embed #Main > .wrapper {
+       padding: 0;
+}
+
+body#embed .logo {
+       padding-top: 4px;
+}
+
+body#embed ul.custom {
+       display: inline-block;
+       width: calc(100% - 72px);
+}
+
+body#embed ul.custom .soundfile-info {
+       padding: 1ex;
+}
+
+body#embed span.fragment-title {
+       font-weight: normal;
+}
+
+table.playlist {
+       width: 90%;
+}
+
+table.playlist td {
+       padding: 0.5ex;
+       text-align: left;
+}
+
+table.playlist td.tracktime {
+       width: 6ex;
+       text-align: center;
+}
+
+p.playlist-disclaimer {
+       margin-top: 2em;
+       max-width: 60ex;
+       font-style: italic;
+}
+
+
+#main-topiks #fiber-nav li ul {
+    padding-top: 0;
+    padding-left: 2em;
+}
+#main-topiks #fiber-nav li ul li {
+    padding-left: 0;
+    font-size: 80%;
+}
+
+#main-topiks #fiber-nav li ul li a {
+    padding-left: 0;
+}
+
+div.commands {
+       display: flex;
+       width: 90vw;
+}
+
+@media screen and (min-width:760px){
+       div.commands {
+               width: calc(90vw - 240px);
+       }
+}
+
+input#msg {
+       flex-grow: 1;
+}
+
+div.chat-area {
+       max-width: 60em;
+}
+
+#chat {
+       margin-top: 1ex;
+}
+
+#chat div.msg {
+        position: relative;
+        margin-bottom: 1ex;
+        transition: opacity 1s ease;
+}
+
+#chat div.msg.new {
+        opacity: 0;
+}
+
+#chat div.msg.msg-out span.content {
+        font-size: 90%;
+        color: #444;
+}
+
+#chat span.from {
+   display: inline-block;
+   width: 10rem;
+   overflow: hidden;
+   text-overflow: ellipsis;
+   color: #888;
+   position: absolute;
+}
+#chat span.content {
+  display: inline-block;
+  padding-left: 11rem;
+}
+
+#chat div.msg.info span.content {
+       padding-left: 1rem;
+       font-style: italic;
+       color: #666;
+}
+
+@media screen and (max-width: 760px) {
+    #chat span.from {
+        display: block;
+        position: static;
+        width: auto;
+    }
+    #chat span.content {
+        display: block;
+        padding-left: 2rem;
+    }
+}
+
+h1.top > span.chat.with-logo {
+       position: relative;
+       left: 140px;
+       display: inline-block;
+       max-width: calc(100% - 140px);
+}
+
+div.top-logo {
+       position: absolute;
+       top: 30px;
+}
+
+div.top-logo img {
+       border: 2px solid black;
+}
+
+@media screen and (max-width:760px){
+       div.top-logo {
+               display: none;
+       }
+       h1.top > span.chat.with-logo {
+               position: static;
+               max-width: none;
+       }
+       div.topikcellcontent a {
+               width: auto;
+       }
+       #fiber-content div.topikcell a {
+               height: auto;
+       }
+}
+
+div#CurrentlyChatting {
+       cursor: pointer;
+       margin-top: 1em;
+}
+
+div.description-emission-chat {
+       margin-bottom: 2em;
+}
+
+div.chatPart h3 {
+       padding-top: 0;
+}
+
+div#chat.moderation .msg-in span.from {
+       cursor: pointer;
+}
+
+div#chat.moderation .msg-in span.from:hover::after {
+       padding-left: 1ex;
+       font-family: FontAwesome;
+       content: "\f056";
+       font-size: 80%;
+}
+
+div.programCell a.playlist {
+       font-size: 80%;
+}
+
+#bg-title {
+       display: none;
+       color: lighten($primary, 20);
+       font-family: 'Reglo';
+       text-transform: uppercase;
+       line-height: 100%;
+       font-size: 250px;
+       font-size: 25vh;
+       position: absolute;
+       left: -260px;
+       top: 48vh;
+       z-index: 0;
+       -webkit-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+       cursor: default;
+}
+
+.rightPart .menucell {
+       ul {
+               list-style: none;
+               padding: 0;
+               li {
+                       padding-bottom: 1rem;
+               }
+       }
+}
+
+div#loading-page {
+       position: fixed;
+       top: 0;
+       left: 0;
+       right: 0;
+       height: 5px;
+       background: $secondary;
+       z-index: 1100;
+       animation-name: load_animation;
+       animation-duration: 6000ms;
+       animation-timing-function: ease-out;
+       transition: opacity 200ms linear;
+       &.fade {
+               opacity: 0;
+       }
+}
+
+@keyframes load_animation {
+       0% { right: 100%; }
+       100% { right: 0%; }
+}
+
+.episode-auto-selection-cell.hide-emission-titles {
+       .emission-title, .soundfile-info .sep {
+               display: none;
+       }
+}
diff --git a/panikweb/static/css/_type.scss b/panikweb/static/css/_type.scss
new file mode 100644 (file)
index 0000000..5a4e581
--- /dev/null
@@ -0,0 +1,133 @@
+@font-face {
+    font-family: 'RegloNormal';
+    src: url('../reglo/RE01.otf');
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: 'RegloMedium';
+    src: url('../reglo/RE02-Medium.otf');
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: 'RegloBold';
+    src: url('../reglo/RE03-Bold.otf');
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: 'RE04';
+    src: url('../reglo/RE04-Bold.otf');
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: 'RE05';
+    src: url('../reglo/RE05-Bold.otf');
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: 'RegloSymbol';
+    src: url('../reglo/RE06.otf');
+    font-weight: normal;
+    font-style: normal;
+       line-height: 0 !important;
+}
+
+@font-face {
+    font-family: 'Reglo';
+    src: url('../reglo/Reglo-Bold.otf');
+    font-weight: normal;
+    font-style: normal;
+}
+@font-face {
+    font-family: 'Symbols';
+    src: url('../reglo/RESYMBOL-resized.otf');
+    font-weight: normal;
+    font-style: normal;
+}
+@font-face {
+    font-family: 'SymbolsResized';
+    src: url('../reglo/RESYMBOL-resized.otf');
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: 'RegloScale';
+    src: url('../reglo/RegloScaleBold.otf');
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: 'Montserrat';
+    src: url('../fonts/Montserrat-Regular.ttf');
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: 'Montserrat';
+    src: url('../fonts/Montserrat-Bold.ttf');
+    font-weight: bold;
+    font-style: normal;
+}
+
+[class^="icon-"],
+[class*=" icon-"]{
+       /*font-size:1.3em;*/
+}
+.resymbol{
+       vertical-align: middle;
+       display: inline-block;
+       font-family: 'Symbols';
+}
+.resymbol.big, .icons.big{
+       font-size:2em;
+}
+.resymbol.huge, .icons.huge{
+       font-size:3em;
+}
+.info:before,.warning:before,.error:before{
+       font-family: FontAwesome;
+       display:inline-block;
+       margin-right:0.2em;
+}
+.info:before {
+       content: "\f05a";
+}
+.warning:before {
+       content: "\f071";
+}
+.error:before {
+       content: "\f056 ";
+}
+.checked:before {
+       content: "\f056 ";
+}
+                       
+.icon-communautaire:before {
+  content: "▲"; /* &#9652; */
+}                      
+.icon-musique:before {
+  content: "△"; /* &#9653; */
+}              
+.icon-creation:before {
+  content: "○"; /* &#9675; */
+}                      
+.icon-agenda-culturel:before {
+  content: "●"; /*  &#9679; */
+}
+.icon-infodebats:before {
+  content: "■"; /*  &#9632; */
+  /*content: "□ ";   &#9633; */
+}
+
diff --git a/panikweb/static/css/style.scss b/panikweb/static/css/style.scss
new file mode 100644 (file)
index 0000000..e54f583
--- /dev/null
@@ -0,0 +1,8 @@
+$very-small-limit: 400px;
+$mobile-limit: 760px;
+
+@import 'reset';
+@import 'type';
+@import 'general';
+@import 'grid';
+@import 'specifics';
diff --git a/panikweb/static/fonts/Montserrat-Bold.ttf b/panikweb/static/fonts/Montserrat-Bold.ttf
new file mode 100644 (file)
index 0000000..ae33a45
Binary files /dev/null and b/panikweb/static/fonts/Montserrat-Bold.ttf differ
diff --git a/panikweb/static/fonts/Montserrat-Regular.ttf b/panikweb/static/fonts/Montserrat-Regular.ttf
new file mode 100644 (file)
index 0000000..5b4b5af
Binary files /dev/null and b/panikweb/static/fonts/Montserrat-Regular.ttf differ
diff --git a/panikweb/static/img/LogoPanik.jpg b/panikweb/static/img/LogoPanik.jpg
new file mode 100644 (file)
index 0000000..ff4bc8d
Binary files /dev/null and b/panikweb/static/img/LogoPanik.jpg differ
diff --git a/panikweb/static/img/Radio_Panik_Logo_2016-01.png b/panikweb/static/img/Radio_Panik_Logo_2016-01.png
new file mode 100644 (file)
index 0000000..3bcd0ec
Binary files /dev/null and b/panikweb/static/img/Radio_Panik_Logo_2016-01.png differ
diff --git a/panikweb/static/img/actu.png b/panikweb/static/img/actu.png
new file mode 100644 (file)
index 0000000..76e39e2
Binary files /dev/null and b/panikweb/static/img/actu.png differ
diff --git a/panikweb/static/img/defaultLogo.png b/panikweb/static/img/defaultLogo.png
new file mode 100644 (file)
index 0000000..5e5d18d
Binary files /dev/null and b/panikweb/static/img/defaultLogo.png differ
diff --git a/panikweb/static/img/emission.png b/panikweb/static/img/emission.png
new file mode 100644 (file)
index 0000000..b71efb2
Binary files /dev/null and b/panikweb/static/img/emission.png differ
diff --git a/panikweb/static/img/episode.png b/panikweb/static/img/episode.png
new file mode 100644 (file)
index 0000000..7ec7cad
Binary files /dev/null and b/panikweb/static/img/episode.png differ
diff --git a/panikweb/static/img/favicon-16.png b/panikweb/static/img/favicon-16.png
new file mode 100644 (file)
index 0000000..30ef6a2
Binary files /dev/null and b/panikweb/static/img/favicon-16.png differ
diff --git a/panikweb/static/img/favicon-32.png b/panikweb/static/img/favicon-32.png
new file mode 100644 (file)
index 0000000..9bdbcff
Binary files /dev/null and b/panikweb/static/img/favicon-32.png differ
diff --git a/panikweb/static/img/favicon-48.png b/panikweb/static/img/favicon-48.png
new file mode 100644 (file)
index 0000000..3c294b0
Binary files /dev/null and b/panikweb/static/img/favicon-48.png differ
diff --git a/panikweb/static/img/favicon.png b/panikweb/static/img/favicon.png
new file mode 100644 (file)
index 0000000..64aa09e
Binary files /dev/null and b/panikweb/static/img/favicon.png differ
diff --git a/panikweb/static/img/logo-2016.png b/panikweb/static/img/logo-2016.png
new file mode 100644 (file)
index 0000000..b7c90da
Binary files /dev/null and b/panikweb/static/img/logo-2016.png differ
diff --git a/panikweb/static/img/logo-panik-500-invert.png b/panikweb/static/img/logo-panik-500-invert.png
new file mode 100644 (file)
index 0000000..64ff785
Binary files /dev/null and b/panikweb/static/img/logo-panik-500-invert.png differ
diff --git a/panikweb/static/img/logo-panik-500.png b/panikweb/static/img/logo-panik-500.png
new file mode 100644 (file)
index 0000000..0aca001
Binary files /dev/null and b/panikweb/static/img/logo-panik-500.png differ
diff --git a/panikweb/static/img/logo-panik.png b/panikweb/static/img/logo-panik.png
new file mode 100644 (file)
index 0000000..90fd8ac
Binary files /dev/null and b/panikweb/static/img/logo-panik.png differ
diff --git a/panikweb/static/img/logo.jpg b/panikweb/static/img/logo.jpg
new file mode 100644 (file)
index 0000000..7ec2a3d
Binary files /dev/null and b/panikweb/static/img/logo.jpg differ
diff --git a/panikweb/static/img/logoPanik.png b/panikweb/static/img/logoPanik.png
new file mode 100644 (file)
index 0000000..57169b0
Binary files /dev/null and b/panikweb/static/img/logoPanik.png differ
diff --git a/panikweb/static/img/logoPanikBW.png b/panikweb/static/img/logoPanikBW.png
new file mode 100644 (file)
index 0000000..7820f3c
Binary files /dev/null and b/panikweb/static/img/logoPanikBW.png differ
diff --git a/panikweb/static/img/sound.png b/panikweb/static/img/sound.png
new file mode 100644 (file)
index 0000000..f3ec86e
Binary files /dev/null and b/panikweb/static/img/sound.png differ
diff --git a/panikweb/static/js/audioPlayer.js b/panikweb/static/js/audioPlayer.js
new file mode 100644 (file)
index 0000000..3f039c3
--- /dev/null
@@ -0,0 +1,293 @@
+(function($) {
+       var thePlaylist;
+       $.widget( "panik.playlist", {
+               /*
+                       sound = {
+                               source :{
+                                       ogg:"oggURL",
+                                       mp3:"mp3URL"
+                               },
+                               emission: "episode.slug",
+                               episode: "episode.slug",
+                               id:""
+                       }
+               */
+               options: {
+                       playlist: [],
+                       html5audioOptions:{controls:true,preload:"none"},
+                       classes: "",
+                       itemClasses: "",
+                       controlContainer: $('<div>'),
+                       playlistContainer: $('<ol>'),
+                       onLoad: function(){},
+                       onAdd: function(){},
+                       onPlay: function(){},
+                       onUpdate: function(){},
+               },
+               _create: function() {
+               // Initialization logic here
+                       thePlaylist = this;     
+                       this.isActive = false;
+                       this.isLastAdd = false;
+                       this.controlButtons = []
+                       this.debugContainer = $('<pre>').hide();
+                       this.controlContainer = this.options.controlContainer;
+                       this.playlistContainer = this.options.playlistContainer;
+                       this.element.addClass(this.options.classes);    
+                       this.element.append(this.controlContainer);     
+                       this.element.append(this.playlistContainer);
+                       this.element.append(this.debugContainer);
+                       this.playlist = this.options.playlist;
+                       this.buildPlaylistControls();
+                       this.loadPlaylist();
+                       this._update();
+                       this.options.onLoad(this);
+               },
+
+               _setOption: function( key, value ) {
+                       this.options[ key ] = value;
+                       this._update();
+               },
+               _update: function() {   
+                       this.playlist = [];     
+                       this.playlistContainer.find('audio').each(function(){
+                               thePlaylist.playlist.push(thePlaylist.jsonifyAudio($(this)));
+                       });
+                       this.debugContainer.text(
+                               JSON.stringify(this.playlist, null, '\t')
+                       );
+                       this.savePlaylist();
+                       this.options.onUpdate(this);
+                       return this.playlist;
+               },
+               _reset: function() {    
+                       this.isActive =false;
+                       this.stopSounds();
+                       this.playlistContainer.find('*').remove();
+                       this._update();
+               },
+               savePlaylist: function(){
+                       var JSONPlaylist = JSON.stringify(this.playlist, null, '\t');
+                       if (localStorage !== null && localStorage !== undefined) {
+                               localStorage['playlist'] = JSON.stringify(this.playlist, null, '\t');
+                       }
+               },
+               loadPlaylist: function(){
+                       if (localStorage !== null && localStorage !== undefined) {
+                               this.playlist = localStorage['playlist']?JSON.parse(localStorage['playlist']):this.playlist;
+                       }
+                       $.each(this.playlist,function(k,v){
+                               thePlaylist.playlistContainer.append(thePlaylist._htmlifyJsonSound(v));
+                       });
+                       return this.playlist;
+               },
+               // Transform HTML5 <audio> to simple JSON object.
+               jsonifyAudio: function(audio) {
+                       var sound = {
+                               source :{},
+                               title: audio.attr('title'),
+                               sound_id:audio.data('sound-id'),
+                               url:audio.attr('data-url'),
+                               focus:audio.attr('data-player-focus')
+                       };
+                       audio.children('source').each(function(){
+                               sound.source[$(this).attr('type')] = $(this).attr('src');
+                       });
+                       return sound;
+               },
+               // Play next sound
+               setFocus: function(element) {
+                       this.isActive = element;
+                       this.playlistContainer.find('li').each(function(){
+                               $(this).removeClass('active');
+                               $(this).find('audio').removeAttr('data-player-focus');
+                       });
+                       this.isActive.addClass('active').find('audio').attr('data-player-focus',true);
+                       this._update();
+               },
+               // Transform JSON sound object to HTML container for playlist.
+               _htmlifyJsonSound: function(sound) {
+                       var container = $('<li>');
+                       var audio = $('<audio>',this.options.html5audioOptions)
+                               .attr('title',sound.title).hide()
+                               .attr('data-sound-id', sound.sound_id)
+                               .attr('data-url',sound.url);
+                       var audio_str = sound.sound_id + ': ' + sound.title;
+                       $.each(sound.source,function(k,v){
+                               var source = $('<source>',{src:v,type:k});
+                               audio.append(source);
+                       });
+                       audio.on('play',function(e){
+                               if (e.originalEvent === undefined) {
+                                       return;
+                               }
+                               if (typeof (_paq) == 'object') {
+                                       _paq.push(['trackEvent', 'Audio', 'Play', audio_str]);
+                               }
+                               thePlaylist.setFocus(container);
+                               container.addClass('playing');
+                               playpause.addClass('icon-pause').removeClass('icon-play');
+                               thePlaylist.controlButtons['playpause'].removeClass('icon-play').addClass('icon-pause');
+                               thePlaylist.afterPlay();
+                               var sound_id = $(e.target).data('sound-id');
+                               $(document).trigger('panik:play', {'sound_id': sound_id});
+                       }).on('pause',function(e){
+                               $(this).removeClass('playing');
+                               playpause.addClass('icon-play').removeClass('icon-pause');
+                               var sound_id = $(e.target).data('sound-id');
+                               $(document).trigger('panik:pause', {'sound_id': sound_id});
+                               thePlaylist.controlButtons['playpause'].removeClass('icon-pause').addClass('icon-play');
+                       }).on('stop',function(event){
+                               $(this).trigger('pause');
+                               if($(this)[0].currentTime){$(this)[0].currentTime = 0;}
+                       }).on("ended", function(e){
+                               if (typeof (_paq) == 'object') {
+                                       _paq.push(['trackEvent', 'Audio', 'End', audio_str]);
+                               }
+                               thePlaylist.playNext();
+                       }).on('beforePause',function(){
+                               return this;
+                       }).on('beforePlay',function(){
+                               thePlaylist.pauseSounds();
+                               return this;
+                       }).on('timeupdate', function(event) {
+                               var position = 1.0 * event.target.currentTime / event.target.duration;
+                               var sound_id = $(event.target).data('sound-id');
+                               $(document).trigger('panik:timeupdate',
+                                               {'sound_id': sound_id, 'position': position});
+                       });
+                       var controls = $('<span>',{'class':'soundControls controls'});
+                       var link = $('<a>',{href:sound.url,'class':'button icon-external-link'});
+                       var remove = $('<button>',{title:"Remove from list",'class':'icon-remove',click:function(){
+                               audio.trigger('stop');
+                               container.remove();
+                               thePlaylist._update();
+                       }});
+                       var stop = $('<button>',{title:"Stop",'class':'icon-stop',click:function(){
+                               audio.trigger('stop');
+                       }}).hide();
+                       var playpause = $('<button>',{title:"Play/Pause",'class':'icon-play',click:function(){
+                               
+                                 if (audio[0].paused == false) { audio.trigger('pause');
+                                 } else {
+                                       audio.trigger('beforePlay').trigger('play');
+                               }
+                       }});
+                       controls.append(playpause).append(stop).append(remove);
+                       var title = $('<a>',{title:"More information",href:sound.url,'class':"button title",html:sound.title});
+                       container.append(controls).append(title).append(audio);
+                       if(sound.focus){thePlaylist.setFocus(container);}
+                       return container;
+               },
+               // Create a public method.
+               registerAudio: function(audio,success) {
+                       var sound_id = audio.data('sound-id');
+                       if (this.playlistContainer.find('[data-sound-id=' + sound_id + ']').length) {
+                               /* already in playlist */
+                               return;
+                       }
+                       var audioObj = this.jsonifyAudio(audio);
+                       var htmlAudio = this._htmlifyJsonSound(audioObj);
+                       this.playlistContainer.append(htmlAudio);
+                       this.isLastAdd = htmlAudio;
+                       if(!this.isActive){this.setFocus(this.isLastAdd);}
+                       this.options.onAdd(this);
+                       if(success){success();}
+                       this._update();
+               },
+               // Play next sound
+               bindControl: function(control,audio,element,options) {
+                       element.addClass('loading');
+                       audioID = audio.data('souce-id');
+                       //TODO for controls in page content
+               },
+               // Play next sound
+               registerControl: function(name,options) {
+                       this.controlButtons[name] = $('<button>',options);
+                       this.controlContainer.append(this.controlButtons[name]);
+               },
+               // Build controls
+               buildPlaylistControls: function() {
+                       this.controlContainer.empty();
+                       /*
+                       this.registerControl('toggleList',{class:"icon-list",click:     function(){ 
+                               thePlaylist.playlistContainer.toggle();
+                       }});
+                       this.registerControl('clearList',{class:"icon-trash",click:     function(){ 
+                               thePlaylist.playlistContainer.empty();
+                               thePlaylist._update();
+                       }});
+                       */
+                       this.registerControl('previous',{'class':"icon-step-backward",click:function(){
+                               thePlaylist.playPrevious();
+                       }});
+                       this.registerControl('stop',{'class':"icon-stop",click: function(){ 
+                               thePlaylist.stopSounds();
+                       }});
+                       this.registerControl('playpause',{'class':"icon-play playPause",click:  function(){
+                               thePlaylist.playPauseList();
+                       }});
+                       this.registerControl('next',{'class':"icon-step-forward",click: function(){ 
+                               thePlaylist.playNext();
+                       }});
+                       return true;
+               },
+               // Play next sound
+               afterPlay: function() {
+                       this.options.onPlay(this);
+               },
+               // Play next sound
+               beforePlay: function() {
+                       this.stopSounds();
+               },
+               // Play next sound
+               getActive: function() {
+                       if(!this.isActive){
+                               this.isActive = this.playlistContainer.children('li').first();                          
+                       }
+                       return this.isActive;
+               },
+               playSoundId: function(sound_id) {
+                       this.playlistContainer.find('audio[data-sound-id="' + sound_id + '"]'
+                                       ).trigger('beforePlay').trigger('play');
+               },
+               // Play next sound
+               playPauseList: function() {
+                       if(this.controlButtons['playpause'].hasClass('icon-play')){
+                               this.getActive().find('audio').trigger('beforePlay').trigger('play');
+                       }else{
+                               this.getActive().find('audio').trigger('pause');        
+                       }
+                       return true;
+               },
+               // Play next sound
+               playPrevious: function() {
+                       this.getActive().prev().find('audio').trigger('beforePlay').trigger('play');
+                       return true;
+               },
+               // Play next sound
+               playNext: function() {
+                       this.getActive().next().find('audio').trigger('beforePlay').trigger('play');
+                       return true;
+               },
+               // Play next sound
+               playFirst: function() {
+                       this.playlistContainer.find('audio').first().trigger('beforePlay').trigger('play');
+                       return true;
+               },
+               // Play next sound
+               playLast: function() {
+                       this.playlistContainer.find('audio').last().trigger('beforePlay').trigger('play');
+                       return true;
+               },
+               // Pause all sounds.
+               pauseSounds: function() {
+                       this.playlistContainer.find('audio').each(function(){$(this).trigger('pause');});       
+               },
+               // stop all sounds.
+               stopSounds: function() {
+                       this.playlistContainer.find('audio').each(function(){$(this).trigger('stop');});        
+               },
+       });
+})(jQuery);
+
diff --git a/panikweb/static/js/jquery.scrollTo-1.4.3.1-min.js b/panikweb/static/js/jquery.scrollTo-1.4.3.1-min.js
new file mode 100644 (file)
index 0000000..bfe7a67
--- /dev/null
@@ -0,0 +1,7 @@
+/**
+ * Copyright (c) 2007-2012 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
+ * Dual licensed under MIT and GPL.
+ * @author Ariel Flesler
+ * @version 1.4.3.1
+ */
+;(function($){var h=$.scrollTo=function(a,b,c){$(window).scrollTo(a,b,c)};h.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1,limit:true};h.window=function(a){return $(window)._scrollable()};$.fn._scrollable=function(){return this.map(function(){var a=this,isWin=!a.nodeName||$.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!isWin)return a;var b=(a.contentWindow||a).document||a.ownerDocument||a;return/webkit/i.test(navigator.userAgent)||b.compatMode=='BackCompat'?b.body:b.documentElement})};$.fn.scrollTo=function(e,f,g){if(typeof f=='object'){g=f;f=0}if(typeof g=='function')g={onAfter:g};if(e=='max')e=9e9;g=$.extend({},h.defaults,g);f=f||g.duration;g.queue=g.queue&&g.axis.length>1;if(g.queue)f/=2;g.offset=both(g.offset);g.over=both(g.over);return this._scrollable().each(function(){if(e==null)return;var d=this,$elem=$(d),targ=e,toff,attr={},win=$elem.is('html,body');switch(typeof targ){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(targ)){targ=both(targ);break}targ=$(targ,this);if(!targ.length)return;case'object':if(targ.is||targ.style)toff=(targ=$(targ)).offset()}$.each(g.axis.split(''),function(i,a){var b=a=='x'?'Left':'Top',pos=b.toLowerCase(),key='scroll'+b,old=d[key],max=h.max(d,a);if(toff){attr[key]=toff[pos]+(win?0:old-$elem.offset()[pos]);if(g.margin){attr[key]-=parseInt(targ.css('margin'+b))||0;attr[key]-=parseInt(targ.css('border'+b+'Width'))||0}attr[key]+=g.offset[pos]||0;if(g.over[pos])attr[key]+=targ[a=='x'?'width':'height']()*g.over[pos]}else{var c=targ[pos];attr[key]=c.slice&&c.slice(-1)=='%'?parseFloat(c)/100*max:c}if(g.limit&&/^\d+$/.test(attr[key]))attr[key]=attr[key]<=0?0:Math.min(attr[key],max);if(!i&&g.queue){if(old!=attr[key])animate(g.onAfterFirst);delete attr[key]}});animate(g.onAfter);function animate(a){$elem.animate(attr,f,g.easing,a&&function(){a.call(this,e,g)})}}).end()};h.max=function(a,b){var c=b=='x'?'Width':'Height',scroll='scroll'+c;if(!$(a).is('html,body'))return a[scroll]-$(a)[c.toLowerCase()]();var d='client'+c,html=a.ownerDocument.documentElement,body=a.ownerDocument.body;return Math.max(html[scroll],body[scroll])-Math.min(html[d],body[d])};function both(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);
diff --git a/panikweb/static/js/konami.js b/panikweb/static/js/konami.js
new file mode 100644 (file)
index 0000000..5f1dd7c
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+       * Konami-JS ~ 
+       * :: Now with support for touch events and multiple instances for 
+       * :: those situations that call for multiple easter eggs!
+       * Code: http://konami-js.googlecode.com/
+       * Examples: http://www.snaptortoise.com/konami-js
+       * Copyright (c) 2009 George Mandis (georgemandis.com, snaptortoise.com)
+       * Version: 1.4.1 (3/1//2013)
+       * Licensed under the GNU General Public License v3
+       * http://www.gnu.org/copyleft/gpl.html
+       * Tested in: Safari 4+, Google Chrome 4+, Firefox 3+, IE7+, Mobile Safari 2.2.1 and Dolphin Browser
+*/
+
+var Konami = function(callback) {
+       var konami= {
+                       addEvent:function ( obj, type, fn, ref_obj )
+                       {
+                               if (obj.addEventListener)
+                                       obj.addEventListener( type, fn, false );
+                               else if (obj.attachEvent)
+                               {
+                                       // IE
+                                       obj["e"+type+fn] = fn;
+                                       obj[type+fn] = function() { obj["e"+type+fn]( window.event,ref_obj ); }
+                                       obj.attachEvent( "on"+type, obj[type+fn] );
+                               }
+                       },
+               input:"",
+               pattern:"38384040373937396665",         
+               load: function(link) {                                  
+                               this.addEvent(document,"keydown", function(e,ref_obj) {                                                                                 
+                                       if (ref_obj) konami = ref_obj; // IE
+                                       konami.input+= e ? e.keyCode : event.keyCode;
+                                       if (konami.input.length > konami.pattern.length) konami.input = konami.input.substr((konami.input.length - konami.pattern.length));
+                                       if (konami.input == konami.pattern) {
+                    konami.code(link);
+                                       konami.input="";
+                       return;
+                    }
+               },this);
+           this.iphone.load(link);
+
+                               },
+               code: function(link) { window.location=link},
+               iphone:{
+                       start_x:0,
+                       start_y:0,
+                       stop_x:0,
+                       stop_y:0,
+                       tap:false,
+                       capture:false,
+                                       orig_keys:"",
+                       keys:["UP","UP","DOWN","DOWN","LEFT","RIGHT","LEFT","RIGHT","TAP","TAP"],
+                       code: function(link) { konami.code(link);},
+                       load: function(link){
+                                                                       this.orig_keys = this.keys;
+                                                               konami.addEvent(document,"touchmove",function(e){
+                                 if(e.touches.length == 1 && konami.iphone.capture==true){ 
+                                   var touch = e.touches[0]; 
+                                       konami.iphone.stop_x = touch.pageX;
+                                       konami.iphone.stop_y = touch.pageY;
+                                       konami.iphone.tap = false; 
+                                       konami.iphone.capture=false;
+                                       konami.iphone.check_direction();
+                                       }
+                                       });               
+                               konami.addEvent(document,"touchend",function(evt){
+                                       if (konami.iphone.tap==true) konami.iphone.check_direction(link);           
+                                       },false);
+                               konami.addEvent(document,"touchstart", function(evt){
+                                       konami.iphone.start_x = evt.changedTouches[0].pageX;
+                                       konami.iphone.start_y = evt.changedTouches[0].pageY;
+                                       konami.iphone.tap = true;
+                                       konami.iphone.capture = true;
+                                       });               
+                                       },
+                       check_direction: function(link){
+                               x_magnitude = Math.abs(this.start_x-this.stop_x);
+                               y_magnitude = Math.abs(this.start_y-this.stop_y);
+                               x = ((this.start_x-this.stop_x) < 0) ? "RIGHT" : "LEFT";
+                               y = ((this.start_y-this.stop_y) < 0) ? "DOWN" : "UP";
+                               result = (x_magnitude > y_magnitude) ? x : y;
+                               result = (this.tap==true) ? "TAP" : result;                     
+
+                               if (result==this.keys[0]) this.keys = this.keys.slice(1,this.keys.length);
+                               if (this.keys.length==0) { 
+                                                               this.keys=this.orig_keys;
+                                                               this.code(link);
+                                                               }
+                               }
+                       }
+       }
+       
+       typeof callback === "string" && konami.load(callback);
+       if(typeof callback === "function")  {
+               konami.code = callback;
+               konami.load();
+       }
+
+       return konami;
+};
diff --git a/panikweb/static/js/specifics.js b/panikweb/static/js/specifics.js
new file mode 100644 (file)
index 0000000..b18a389
--- /dev/null
@@ -0,0 +1,770 @@
+var urlParams;
+var connection;
+
+(window.onpopstate = function () {
+    var match,
+        pl     = /\+/g,  // Regex for replacing addition symbol with a space
+        search = /([^&=]+)=?([^&]*)/g,
+        decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
+        query  = window.location.search.substring(1);
+
+    urlParams = {};
+    while (match = search.exec(query))
+       urlParams[decode(match[1])] = decode(match[2]);
+})();
+
+$(function() {
+
+       doLog = function(aTextToLog, type){
+               var aLog = $('<div>',{'class':"log "+type,html:aTextToLog});
+               aLog.hide().prependTo($log).show('fast').delay(3000).hide('fast', function() { 
+                       $(this).remove(); 
+               });
+       }
+       var $main = $("#Changing");
+       var $metaNav = $("#metaNav");
+       var $log = $("#userLog");
+
+       /****************************************************/
+       /**** AJAX UTILITIES FOR REQUESTS ****/
+       /****************************************************/
+       String.prototype.decodeHTML = function() {
+               return $("<div>", {html: "" + this}).html();
+       };
+       var loadPage_request = null;
+       afterLoad = function(html, textStatus, XMLHttpRequest) {
+               $('#loading-page').addClass('fade');
+               loadPage_request = null;
+               if (textStatus == "error") {
+                       doLog('Sorry! And error occur when loading page content','error');
+               }
+                if (connection) { connection.disconnect(); }
+               new_html = $.parseHTML(html);
+               new_content = $(new_html).find('#Changing>*');
+               $main.hide().empty().append(new_content).show();
+
+               /* calling onpopstate here is necessary to get urlParams to be
+                * updated */
+               window.onpopstate();
+
+               canonical_href_node = $.grep($(new_html), function(elem, idx) {
+                       return (elem.nodeName === "LINK" && elem.attributes['rel'].value == "canonical");
+               })[0];
+               if (canonical_href_node) {
+                       canonical_href = canonical_href_node.attributes['href'].value;
+                       try { history.replaceState({}, '', canonical_href); } catch(ex) {};
+               }
+
+               new_menu = $($.parseHTML(html)).find('#metaNav>*');
+               $metaNav.empty().append(new_menu);
+
+               var newTitle = html?html.match(/<title>(.*?)<\/title>/):'';
+               if(newTitle){document.title = newTitle[1].trim().decodeHTML();}
+
+               $.scrollTo('#Changing',1000,{offset:-$('#metaNav').height()+2});
+               init();
+
+               if (typeof (Piwik) == 'object') {
+                       piwikTracker = Piwik.getAsyncTracker();
+                       if (typeof (piwikTracker.trackPageView) == 'function') {
+                               piwikTracker.setDocumentTitle(document.title);
+                               piwikTracker.setCustomUrl(window.location.href);
+                               piwikTracker.trackPageView();
+                               $('.audio a').each(function() {
+                                       piwikTracker.addListener(this);
+                               });
+                       }
+               }
+
+       };
+
+       function afterLoadError(xhr, text, error) {
+               afterLoad(xhr.responseText, 'error', xhr);
+       };
+
+       $(window).on("popstate", function(e) {
+               loadPage(location.href, false);
+       });
+
+       loadPage = function(href, push_state) {
+               if (push_state !== false) {
+                       history.pushState({}, '', href);
+               }
+               if (loadPage_request !== null) {
+                       loadPage_request.abort();
+               }
+               $('#loading-page').remove();
+               $('<div id="loading-page"></div>').prependTo($('#All'));
+               loadPage_request = $.ajax({
+                       url: href,
+                       success: afterLoad,
+                       error: afterLoadError,
+                       dataType: 'html'});
+       };
+        $.fn.ajaxifyClick = function(params) {
+               if ($('#df-wpr-sidebar').length > 0) {
+                       /* this is fiber sidebar, it doesn't work well with
+                        * seamless page loading */
+                       return;
+               }
+               this.each(function() {
+                       $(this).unbind('click');
+                       $(this).bind('click',function(e){
+                               var href = $(this).attr("href");
+                               if (e.which == 2) {
+                                       window.open(href, '_blank');
+                                       return false;
+                               }
+                               if (href.match('\.(pdf|odt|ods|doc|xls|docx|xlsx|rtf|zip|rss|atom)$')) {
+                                       /* open files */
+                                       window.location = href;
+                                       return false;
+                               }
+                               $(this).addClass('loading');
+                               /* this checks the link points to a local document, be
+                                * it because it's just a path, or because the server
+                                * part points to the same domain */
+                               if (!href) {
+                                       doLog('No href attributes, unable to load content','error');
+                                       $("#All a, #All area").removeClass('loading');
+                                       return false;
+                               }else if (!$(this).attr('target') && (
+                                               href.indexOf(document.domain) > -1 ||href.indexOf(':') === -1 || href.indexOf(':') > 5
+                                       )) {
+                                       loadPage(href);
+                                       return false;
+                               }else{
+                                       $(this).attr('target','_blank');
+                                       $(this).attr('rel', 'noopener');
+                                       $("#All a, #All area").removeClass('loading');
+                                       return true;
+                               }
+                       });
+               });
+       };
+       /****************************************************/
+       /**** AUDIOPLAYER ****/
+       /****************************************************/
+
+       var timer = null;
+       var ticker_interval = null;
+       $('#WhatsOnAir').on('load',function(){
+               var WhatsOnAir = $(this);
+               $.getJSON('/onair.json', function(onair) {
+                       var onairContainer = $('<span>');
+                       if(onair.data.episode || onair.data.emission) {
+                               if(onair.data.emission){
+                                       $('<a>',{href:onair.data.emission.url,html:onair.data.emission.title}).appendTo(onairContainer).ajaxifyClick();
+                               }
+                               if(onair.data.episode){
+                                       $('<span> - </span>').appendTo(onairContainer);
+                                       $('<a>',{href:onair.data.episode.url,html:onair.data.episode.title}).appendTo(onairContainer).ajaxifyClick();
+                               }
+                       } else if (onair.data.nonstop) {
+                               if (onair.data.nonstop.url) {
+                                       onairContainer = $('<a href="' + onair.data.nonstop.url + '">' + onair.data.nonstop.title + '</a>');
+                               } else {
+                                       onairContainer = $('<span>' + onair.data.nonstop.title + '</span>');
+                               }
+                               if (onair.data.track_title) {
+                                       $('<span> - </span>').appendTo(onairContainer);
+                                       $('<span class="nonstop-track-title">' + onair.data.track_title + '</span>').appendTo(onairContainer);
+                                       if (onair.data.track_artist) {
+                                               $('<span> </span>').appendTo(onairContainer)
+                                               $('<span class="nonstop-track-artist">(' + onair.data.track_artist + ')</span>').appendTo(onairContainer);
+                                       }
+                               }
+                       }
+                       else {
+                               onairContainer = $('<span>Unknown (Probably Non-Stop)</span>');
+                       }
+                       if (onair.data.emission && onair.data.emission.chat) {
+                               $('#CurrentlyChatting a').attr('href', onair.data.emission.chat);
+                               $('#CurrentlyChatting').show();
+                       } else {
+                               $('#CurrentlyChatting').hide();
+                       }
+                       var current_html = WhatsOnAir.html();
+                       var new_html = '<span>' + onairContainer.html() + '</span>';
+                       if (new_html !== current_html) {
+                               WhatsOnAir.fadeOut();
+                               WhatsOnAir.empty().append(onairContainer);
+                               WhatsOnAir.fadeIn();
+                       }
+               });
+       });
+        $('#WhatsOnAir').trigger('load');
+       var refresh_onair_interval = 25000;
+       setInterval("$('#WhatsOnAir').trigger('load');", refresh_onair_interval);
+       $("#DirectStreamPanikControler").on('click',function(e) {
+               e.preventDefault();
+               var stream = $('#DirectStreamPanik').get(0);
+               if (stream.paused == false){
+                       stream.pause();
+               }else{
+                       if (typeof (_paq) == 'object') {
+                               _paq.push(['trackEvent', 'Audio', 'Play Stream']);
+                       }
+                       stream.play();
+               }
+               return false;
+       });
+       $('#DirectStreamPanik').on('play',function(){
+               $('audio:not(#DirectStreamPanik)').each(function(){this.pause();});
+               $('#streamSymbol').removeClass('icon-volume-up').addClass('icon-pause');
+       }).on('pause',function(){
+               //$('audio:not(#DirectStreamPanik)').each(function(){this.pause();});
+               $('#streamSymbol').addClass('icon-volume-up').removeClass('icon-pause');
+       });
+       if($('#player-container').offset()){
+               var topPosition = 0;
+               topPosition = $('#mainHeader > div').offset().top + $('#mainHeader > div').height();
+               $(window).bind('scroll load',function (event) {
+                       //$('#player-container').removeClass('fixed');
+                       var y = $(this).scrollTop() + 60;
+                       if (topPosition!== 0 && y >= topPosition) {
+                               $('#player-container').addClass('fixed').removeClass('normal');
+                       } else {
+                               $('#player-container').removeClass('fixed').addClass('normal');
+                       }
+               });
+       }
+
+       var $localList = $('#localList').playlist({
+               controlContainer: $('<div>',{'class':"playListControls"}).sortable(),
+               playlistContainer: $('<ol>',{id:"myPlaylist",'class':"custom"}).sortable(),
+               onLoad:function(self){
+                       $('#toggleList').on('click',function(){ 
+                               self.playlistContainer.toggleClass('deploy');
+                       });
+                       $('#emptyList').on('click',function(){ 
+                               self._reset();
+                       });
+
+                       if(self.isActive){
+                               self.playlistContainer.scrollTo(self.isActive, 800 );
+                               self.isActive.find('audio').attr('preload',"preload")
+                       }
+                       self.controlButtons['playpause'].addClass('resymbol');
+               },
+               onPlay:function(self){
+                       $('#DirectStreamPanik')[0].pause();
+                       self.playlistContainer.scrollTo(self.isActive, 800 );
+               },
+               onAdd:function(self){
+                       //self.isLastAdd[0].scrollIntoView();
+                       self.isLastAdd.find('a').ajaxifyClick();
+                       self.playlistContainer.scrollTo(self.isLastAdd, 800).delay(1000).scrollTo(self.isActive, 800 ).clearQueue();
+
+                       if (typeof (_paq) == 'object') {
+                               _paq.push(['trackEvent', 'Audio', 'Add to playlist']);
+                       }
+               },
+               onUpdate:function(self){
+                       //doLog(JSON.stringify(self.playlist, null, '\t'));     
+                       if(self.playlist.length >= 1){
+                               self.element.show();
+                               $('#Player').addClass('withPlaylist').removeClass('withoutPlaylist');
+                       }else{
+                               self.element.hide();
+                               $('#Player').removeClass('withPlaylist').addClass('withoutPlaylist');
+                       }
+               }
+       });
+
+       init = function() {
+               $("#All a, #All area").removeClass('loading');
+               $("#All a, #All area").ajaxifyClick();
+               $("#search-form").unbind('submit').on('submit', function(event) {
+                       event.preventDefault();
+                       $(this).addClass('loading');
+                       loadPage($(this).attr('action') + '?' + $(this).serialize());
+               });
+               $(".tabs").each(function() {
+                       var self = $(this);
+                       var about= $($(this).attr("data-tab-about"));
+                       var current = $(this).find("[data-tab].active")[0];
+                       var dftShowSelector = current?".active":":first";
+                       var activeTab = $(this).find("[data-tab]"+dftShowSelector+"").addClass("active");
+                       $(this).find("[data-tab]").each(function() {
+                           $(this).on('click load',function (e) {  
+                               e.preventDefault();
+                               self.find(".active").removeClass("active");  
+                               $(this).addClass("active");  
+                               about.find("[data-tabbed]").hide();  
+                               $($(this).attr("data-tab")).fadeIn();  
+               
+                           });  
+                       });  
+                       activeTab.trigger('load');
+               });
+               $('[data-player-action]').on('click',function(){
+                       var audio = $('audio[data-sound-id=' + $(this).attr('data-sound-id') + ']');
+                       var sound_id = audio.data('sound-id');
+                       if($(this).attr('data-player-action') == "registerAudio"){
+                               $localList.playlist("registerAudio",audio);
+                       }else if($(this).attr('data-player-action') == "playAudio"){
+                               if ($(this).hasClass('icon-play-sign')) {
+                                       $localList.playlist("registerAudio",audio);
+                                       $localList.playlist("playSoundId", sound_id);
+                                       if ($(this).parent().find('.icon-pause').length) {
+                                               $(this).hide();
+                                               $(this).parent().find('.icon-pause').show();
+                                       }
+                               } else {
+                                       $localList.playlist('pauseSounds');
+                               }
+                       }else if ($(this).attr('data-player-action') == "pauseSounds") {
+                               if ($(this).parent().find('.icon-play-sign').length) {
+                                       $(this).hide();
+                                       $(this).parent().find('.icon-play-sign').show();
+                               }
+                               $localList.playlist($(this).attr('data-player-action'));
+                       }else{
+                               $localList.playlist($(this).attr('data-player-action'));
+                       }
+               });
+               $('[data-player-control]').each(function(){
+                       var audio = $('audio[data-sound-id=' + $(this).attr('data-sound-id') + ']');
+                       $localList.playlist("bindControl",$(this).attr('data-player-control'),audio,$(this));
+               });
+
+               $('[data-highlight]').on('check',function(){
+                       $($(this).attr('data-about')).find($(this).attr('data-highlight')).addClass('highlighted').removeClass('normal');
+               }).on('uncheck',function(){
+                       $($(this).attr('data-about')).find($(this).attr('data-highlight')).removeClass('highlighted').addClass('normal');
+               }).on('click',function(){
+                       $(this).toggleClass('icon-check icon-check-empty');
+                       if($(this).hasClass('icon-check')){$(this).trigger('check');
+                       }else{  $(this).trigger('uncheck');}
+               });
+               $('[data-highlight].icon-check-empty').each(function(){
+                       $(this).trigger('uncheck');
+               });
+               $('[data-toggle]').on('check',function(){
+                       /* make sure all other unchecked items are hidden */
+                       $('[data-toggle].icon-check-empty').each(function() {
+                               $($(this).attr('data-about')).find($(this).attr('data-toggle')).hide();
+                       });
+                       $($(this).attr('data-about')).find($(this).attr('data-toggle')).show();
+               }).on('uncheck',function(){
+                       $($(this).attr('data-about')).find($(this).attr('data-toggle')).hide();
+                       if ($('[data-toggle].icon-check').length == 0) {
+                               /* special case the situation where all toggles
+                                * are unchecked, as we want that to mean
+                                * "everything", not "nothing".
+                                */
+                               $('[data-toggle].icon-check-empty').each(function() {
+                                       $($(this).attr('data-about')).find($(this).attr('data-toggle')).show();
+                               });
+                       }
+               }).on('click',function(){
+                       $(this).toggleClass('icon-check icon-check-empty');
+                       if($(this).hasClass('icon-check')){$(this).trigger('check');
+                       }else{  $(this).trigger('uncheck');}
+               });
+               $('[data-toggle].icon-check-empty').each(function(){
+                       $(this).trigger('uncheck');
+               });
+
+               initial_enabled_toggles = {};
+               if (typeof(urlParams.q) == 'string') {
+                       urlParams.q.split('|').forEach(function(a) { initial_enabled_toggles[a] = 1; })
+               }
+               $('[data-toggle]').each(function() {
+                       if ($(this).data('toggle').substring(1) in initial_enabled_toggles) {
+                               $(this).trigger('click');
+                       }
+               });
+
+               $('[data-popup-href]').on('click', function() {
+                       $.ajax({
+                               url: $(this).data('popup-href'),
+                               success: function (html, textStatus, jqXhr) {
+                                       $(html).appendTo($('body'));
+                               }
+                       });
+                       return false;
+               });
+
+               if ($('#search-form.big input#id_q').val() == '') {
+                       $('#search-form.big input#id_q').focus();
+               }
+
+                $('#ticker li:not(:first)');
+               if (ticker_interval) clearInterval(ticker_interval);
+               function tick(){
+                   $('#ticker li:first').animate({'opacity':0}, 200, function () {
+                       $(this).appendTo($('#ticker')).css('opacity', 1);
+                   });
+               }
+               $("#roller button").on('click',function(e){
+                   clearInterval(ticker_interval);
+                   e.preventDefault();
+                   $($(this).attr('data-about')).prependTo('#ticker');
+                   return false;
+               });
+               ticker_interval = setInterval(function(){tick();  }, 20000);/**/
+
+               function navsearch_click(event) {
+                       event.preventDefault();
+                       var query = $('#nav-search input').val();
+                       var form = $('#nav-search form');
+                       var href = '';
+                       if (query == '') {
+                               href = $(form).attr('action');
+                       } else {
+                               href = $(form).attr('action') + '?' + $(form).serialize();
+                       }
+                       if (event.which == 2) {
+                               window.open(href, '_blank');
+                       } else {
+                               $(this).addClass('loading');
+                               loadPage(href);
+                       }
+                       return false;
+               }
+               $('#nav-search a').unbind('click').on('click', navsearch_click);
+               $('#nav-search form').unbind('submit').on('submit', navsearch_click);
+
+               if ($('.bg-title').length) {
+                       var bg_title = $('<span id="bg-title" aria-hidden="true"></span>');
+                       bg_title.text($('.bg-title').text());
+                       $('#Changing').append(bg_title);
+               }
+               $('[data-toggle-img]').bind('click', function() {
+                       var src = $(this).data('toggle-img');
+                       $(this).data('toggle-img', $(this).attr('src'));
+                       $(this).attr('src', src);
+                       $(this).toggleClass('right marged');
+               });
+
+               $('#Main #Emission-tabs-detail audio, div.soundcell audio').each(function(index, audio) {
+                       var audio_src = $(audio).find('source')[0];
+                       var sound_id = $(audio).data('sound-id');
+                       var $waveform = $(audio).next();
+                       $.getJSON(audio_src.src.replace('.ogg', '.waveform.json'), function(data) {
+                               $waveform.empty();
+                               $waveform.append('<i class="duration">' + $waveform.data('duration-string') + '</i>');
+                               $.each(data, function(k, val) {
+                                       var val = val * 0.5;
+                                       $waveform.append('<span data-tick-index="' + k + '" style="height: ' + val + 'px;"></span>');
+                               });
+                               $waveform.show();
+                               $waveform.find('span').on('click', function() {
+                                       /* if there's been something loaded */
+                                       var matching_audio = $('audio[data-sound-id=' + sound_id + ']');
+                                       if (matching_audio.length == 0) return;
+                                       matching_audio = matching_audio[0];
+                                       if (matching_audio.paused || matching_audio.ended) {
+                                               $(this).parents('.sound').find('.icon-play-sign').click();
+                                               return;
+                                       }
+                                       /* try to set time */
+                                       var total_duration = parseFloat($waveform.data('duration'));
+                                       var nb_ticks = $(this).parent().find('span').length;
+                                       var tick_index = $(this).data('tick-index');
+                                       matching_audio.currentTime = total_duration * tick_index / nb_ticks;
+                               });
+                       });
+               });
+
+               $('#nav-language span').click(function() {
+                       document.cookie = 'panikweb_language=' + $(this).data('lang') + '; path=/';
+                       window.location = window.location;
+                       return false;
+               });
+
+               if ($('.sound + .content .text  ').length) {
+                       var text_content = $('.sound + .content .text')[0];
+                       text_content.innerHTML = text_content.innerHTML.replace(
+                               /[0-9][0-9]+:[0-9][0-9]/g,
+                               function(x) { return '<span class="timestamp">' + x + "</span>"; });
+                       $(text_content).find('span.timestamp').on('click', function() {
+                               var $waveform = $('div.waveform').first();
+                               var sound_id = $waveform.prev().data('sound-id');
+                               var total_duration = parseFloat($waveform.data('duration'));
+                               var nb_ticks = $waveform.find('span').length;
+                               var timestamp = $(this).text().split(':');
+                               var timestamp_position = timestamp[0] * 60 + timestamp[1] * 1;
+                               var tick_idx = parseInt(nb_ticks * timestamp_position / total_duration);
+                               // play, then set rough position
+                               $('.episode.detail .icon-play-sign').first().trigger('click');
+                               var matching_audio = $('audio[data-sound-id=' + sound_id + ']');
+                               matching_audio[0].currentTime = timestamp_position;
+                       });
+               }
+
+               if (document.cookie.indexOf('panikdb=on') != -1) {
+                       panikdb_path = null;
+                       if (window.location.pathname.indexOf('/emissions/') == 0) {
+                               panikdb_path = window.location.pathname;
+                       } else if (window.location.pathname.indexOf('/news/') == 0) {
+                               panikdb_path = '/emissions' + window.location.pathname;
+                       }
+                       if (panikdb_path) {
+                               $('<a id="panikdb" href="http://panikdb.radiopanik.org' + panikdb_path + '">Voir dans PanikDB</a>').appendTo($main);
+                       }
+               }
+
+               $('.gallery').each(function() {
+                 var $gallery = $(this);
+                 $gallery.find('span.image').on('click', function() {
+                   if ($(this).find('img').hasClass('portrait')) {
+                       $(this).parents('.gallerycell').addClass('portrait');
+                   } else {
+                       $(this).parents('.gallerycell').removeClass('portrait');
+                   }
+                   $gallery.find('div.first img').attr('src', $(this).data('image-large'));
+                   $gallery.find('div.first span.gallery-legend').text($(this).find('img').attr('title') || '');
+                   $gallery.find('div.first').show('fade');
+                   return false;
+                 });
+                 $gallery.find('div.first').on('click', function() { $(this).toggle('fade'); return false; });
+               });
+
+                /* CHAT */
+                if ($('#chat').length) {
+                    $('#player').addClass('on-chat-page');
+                    var moderator = ($('#panikdb').length > 0);
+                    var $msg = $('input#msg');
+                    var $send = $('button#send');
+                    var chat_roster = Object();
+
+                    if (moderator) {
+                      $('#chat').addClass('moderation');
+                      $('#chat').on('click', 'span.from', function() {
+                        var name = $(this).text();
+                        if (confirm('Kick ' + name + ' ?')) {
+                          var muc = $('div#chat').data('chatroom');
+                          connection.muc.kick(muc + '@conf.panik', name,
+                                          'no reason',
+                                          function(iq) {
+                                          },
+                                          function(iq) {
+                                            doLog('error kicking', 'error');
+                                          }
+                          );
+                        }
+                      });
+                    }
+
+                    $('.nick input').on('keydown', function(ev) {
+                        if (ev.keyCode == 13) {
+                            $('.nick button').trigger('click');
+                            return false;
+                        }
+                        return true;
+                    });
+
+                    $('.nick button').on('click', function() {
+                      window.localStorage['pa-nick'] = $('.nick input').val();
+                      var nick = window.localStorage['pa-nick'];
+                      $('.commands .prompt').text(nick + '>');
+
+                      connection = new Strophe.Connection("/http-bind");
+                      connection.connect('im.panik', null, function(status, error) {
+                        if (status == Strophe.Status.CONNECTING) {
+                            $('.nick').show();
+                            $('.commands').hide();
+                            //console.log('Strophe is connecting.');
+                        } else if (status == Strophe.Status.CONNFAIL) {
+                            $('.nick').show();
+                            $('.commands').hide();
+                            //console.log('Strophe failed to connect.');
+                        } else if (status == Strophe.Status.DISCONNECTING) {
+                            $('.nick').show();
+                            $('.commands').hide();
+                            //console.log('Strophe is disconnecting.');
+                        } else if (status == Strophe.Status.DISCONNECTED) {
+                            $('.nick').show();
+                            $('.commands').hide();
+                            //console.log('Strophe is disconnected.');
+                        } else if (status == Strophe.Status.CONNECTED) {
+                            //console.log('Strophe is connected');
+                            $('.nick').hide();
+                            $('.commands').show();
+                            var jid = nick;
+                            var muc = $('div#chat').data('chatroom');
+                            connection.muc.join(muc + '@conf.panik', jid,
+                                    function(msg) {
+                                        var from = msg.attributes.from.value.replace(/.*\//, '');
+                                        var klass = '';
+                                        if (from == jid) {
+                                            klass = 'msg-out';
+                                        } else {
+                                            klass = 'msg-in';
+                                        }
+                                        var new_msg = $('<div class="msg new ' + klass + '"><span class="from">' + from + '</span> <span class="content">' + msg.textContent + '</span></div>').prependTo($('#chat'));
+                                        new_msg[0].offsetHeight; /* trigger reflow */
+                                        new_msg.removeClass('new');
+                                        $('div#chat div:nth-child(20)').remove()
+                                        return true;
+                                    },
+                                    function(pres) {
+                                            var nick = $('.nick input').val()
+                                            var muc = $('div#chat').data('chatroom');
+                                            if (pres.getElementsByTagName('status').length == 1 &&
+                                                pres.getElementsByTagName('status')[0].attributes &&
+                                                pres.getElementsByTagName('status')[0].attributes.code &&
+                                                pres.getElementsByTagName('status')[0].attributes.code.value == '307') {
+                                              /* kicked */
+                                              var kicked = pres.getElementsByTagName('item')[0].attributes.nick.value;
+                                              var new_msg = $('<div class="msg info new"><span class="content">' + kicked + ' a été mis dehors.</span></div>').prependTo($('#chat'));
+                                              new_msg[0].offsetHeight; /* trigger reflow */
+                                              new_msg.removeClass('new');
+                                              if (kicked == nick) {
+                                                connection.disconnect();
+                                                $('div.nick').css('visibility', 'hidden');
+                                              }
+                                            }
+                                            if (pres.getElementsByTagName('conflict').length == 1) {
+                                              $('.nick input').val(nick + '_');
+                                              connection.disconnect();
+                                              $('.nick button').trigger('click');
+                                            }
+                                            return true;
+                                    },
+                                    function(roster) {
+                                            if (chat_roster[nick] == true) {
+                                                for (contact in roster) {
+                                                        if (chat_roster[contact] !== true) {
+                                                                var new_msg = $('<div class="msg info new"><span class="content">' + contact + ' est dans la place.</span></div>').prependTo($('#chat'));
+                                                                new_msg[0].offsetHeight; /* trigger reflow */
+                                                                new_msg.removeClass('new');
+                                                        }
+                                                }
+                                            }
+                                            chat_roster = Object();
+                                            for (contact in roster) {
+                                                chat_roster[contact] = true;
+                                            }
+                                            return true;
+                                    }
+                                    );
+                            }
+                         });
+
+                    });
+
+                    function send() {
+                        var text = $msg.val();
+                        var muc = $('div#chat').data('chatroom');
+                        connection.muc.message(muc + '@conf.panik', null, text);
+                        $msg.val('');
+                        return true;
+                    }
+                    $send.click(send);
+                    $msg.keydown(function(ev) {
+                        if (ev.keyCode == 13) {
+                            send();
+                            return false;
+                        }
+                        return true;
+                    });
+
+                    if (window.localStorage['pa-nick'] !== undefined) {
+                      $('.nick input').val(window.localStorage['pa-nick']);
+                      $('.nick button').click();
+                    }
+
+                    $(window).on('beforeunload', function() {
+                        if (connection) { connection.disconnect(); }
+                    });
+
+                } else {
+                    $('#player').removeClass('on-chat-page');
+                }
+       }
+       init();
+
+       if (! document.createElement('audio').canPlayType('audio/ogg') &&
+               document.createElement('audio').canPlayType('audio/aac') ) {
+               $('#ogg-m3u').hide().removeClass('resymbol');
+               $('#aac-m3u').addClass('resymbol').show();
+       }
+
+       var konami = new Konami('/party');
+
+       $(document).on('panik:play', function(ev, data) {
+               var $page_audio_controls = $('#Main').find('div.audio[data-sound-id="' + data.sound_id + '"]');
+               $page_audio_controls.find('.icon-play-sign').removeClass('icon-play-sign').addClass('icon-pause');
+       });
+
+       $(document).on('panik:pause', function(ev, data) {
+               var $page_audio_controls = $('#Main').find('div.audio[data-sound-id="' + data.sound_id + '"]');
+               $page_audio_controls.find('.icon-pause').removeClass('icon-pause').addClass('icon-play-sign');
+       });
+
+
+       $(document).on('panik:timeupdate', function(ev, data) {
+               var $page_audio_controls = $('#Main').find('div.audio[data-sound-id="' + data.sound_id + '"]');
+               $page_audio_controls.find('.icon-play-sign').removeClass('icon-play-sign').addClass('icon-pause');
+               $waveform = $('#Main div.waveform[data-sound-id="' + data.sound_id + '"]');
+               var elems = $waveform.find('span');
+               var total_elems = elems.length;
+               var done = total_elems * data.position;
+               $waveform.find('span').each(function(k, elem) {
+                 if (k < done) {
+                       $(elem).addClass('done').removeClass('current');
+                 } else {
+                       $(elem).removeClass('done');
+                 }
+               });
+               $waveform.find('span.done:last').addClass('current');
+       });
+
+       $("body").keydown(function(e) {
+         var $visible_element = $('div.first:visible img');
+         if ($visible_element.length == 0) {
+           return true;
+         }
+         if ($visible_element.length > 1) {
+           /* remove all but last */
+           $visible_element.parent().find('img:not(:last)').remove();
+         }
+         var $visible_element = $('div.first:visible img');
+         var img_url = $visible_element.attr('src');
+         var all_img = $('div.gallery span[data-image-large] img');
+         var active_img = $('div.gallery span[data-image-large="' + img_url + '"] img');
+         var idx = all_img.index(active_img);
+         if (e.which == 37) { // left
+           idx--;
+           if (idx == -1) {
+             idx = all_img.length-1;
+           }
+         } else if (e.which == 39) { // right
+           idx++;
+           if (idx == all_img.length) {
+             idx = 0;
+           }
+         } else if (e.which == 27) { // escape
+           $visible_element.parent().toggle('fade');
+           return true;
+         } else {
+           return true;
+         }
+         /* create a new <img> with the new image but opacity 0, then display
+          * it using a css transition */
+         if (e.which == 37) { $visible_element.css('transform-origin', 'bottom right'); }
+         if (e.which == 39) { $visible_element.css('transform-origin', 'bottom left'); }
+         var new_img = $visible_element.clone().appendTo($visible_element.parent());
+         $(new_img).css('opacity', 0).attr('src', $(all_img[idx]).parent().data('image-large'));
+         $(new_img).css('transform', 'scale(0, 1)');
+         $(new_img)[0].offsetHeight; /* trigger reflow */
+         $(new_img).css('opacity', 1).css('transform', 'scale(1)');
+         $(new_img).parents('.gallery').find('span.gallery-legend').text($(all_img[idx]).attr('title') || '');
+         if ($(all_img[idx]).hasClass('portrait')) {
+           if (! $(new_img).parents('.gallerycell').hasClass('portrait')) {
+             $visible_element.parent().find('img:not(:last)').remove();
+             $(new_img).parents('.gallerycell').addClass('portrait');
+           }
+         } else {
+           if ($(new_img).parents('.gallerycell').hasClass('portrait')) {
+             $visible_element.parent().find('img:not(:last)').remove();
+             $(new_img).parents('.gallerycell').removeClass('portrait');
+           }
+         }
+         return false;
+       });
+});
diff --git a/panikweb/static/js/strophe.min.js b/panikweb/static/js/strophe.min.js
new file mode 100644 (file)
index 0000000..9f53dd9
--- /dev/null
@@ -0,0 +1 @@
+var Base64=(function(){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var obj={encode:function(input){var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;do{chr1=input.charCodeAt(i++);chr2=input.charCodeAt(i++);chr3=input.charCodeAt(i++);enc1=chr1>>2;enc2=((chr1&3)<<4)|(chr2>>4);enc3=((chr2&15)<<2)|(chr3>>6);enc4=chr3&63;if(isNaN(chr2)){enc3=enc4=64}else{if(isNaN(chr3)){enc4=64}}output=output+keyStr.charAt(enc1)+keyStr.charAt(enc2)+keyStr.charAt(enc3)+keyStr.charAt(enc4)}while(i<input.length);return output},decode:function(input){var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=(enc1<<2)|(enc2>>4);chr2=((enc2&15)<<4)|(enc3>>2);chr3=((enc3&3)<<6)|enc4;output=output+String.fromCharCode(chr1);if(enc3!=64){output=output+String.fromCharCode(chr2)}if(enc4!=64){output=output+String.fromCharCode(chr3)}}while(i<input.length);return output}};return obj})();function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length*8))}function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length*8))}function b64_hmac_sha1(key,data){return binb2b64(core_hmac_sha1(key,data))}function str_hmac_sha1(key,data){return binb2str(core_hmac_sha1(key,data))}function core_sha1(x,len){x[len>>5]|=128<<(24-len%32);x[((len+64>>9)<<4)+15]=len;var w=new Array(80);var a=1732584193;var b=-271733879;var c=-1732584194;var d=271733878;var e=-1009589776;var i,j,t,olda,oldb,oldc,oldd,olde;for(i=0;i<x.length;i+=16){olda=a;oldb=b;oldc=c;oldd=d;olde=e;for(j=0;j<80;j++){if(j<16){w[j]=x[i+j]}else{w[j]=rol(w[j-3]^w[j-8]^w[j-14]^w[j-16],1)}t=safe_add(safe_add(rol(a,5),sha1_ft(j,b,c,d)),safe_add(safe_add(e,w[j]),sha1_kt(j)));e=d;d=c;c=rol(b,30);b=a;a=t}a=safe_add(a,olda);b=safe_add(b,oldb);c=safe_add(c,oldc);d=safe_add(d,oldd);e=safe_add(e,olde)}return[a,b,c,d,e]}function sha1_ft(t,b,c,d){if(t<20){return(b&c)|((~b)&d)}if(t<40){return b^c^d}if(t<60){return(b&c)|(b&d)|(c&d)}return b^c^d}function sha1_kt(t){return(t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514}function core_hmac_sha1(key,data){var bkey=str2binb(key);if(bkey.length>16){bkey=core_sha1(bkey,key.length*8)}var ipad=new Array(16),opad=new Array(16);for(var i=0;i<16;i++){ipad[i]=bkey[i]^909522486;opad[i]=bkey[i]^1549556828}var hash=core_sha1(ipad.concat(str2binb(data)),512+data.length*8);return core_sha1(opad.concat(hash),512+160)}function safe_add(x,y){var lsw=(x&65535)+(y&65535);var msw=(x>>16)+(y>>16)+(lsw>>16);return(msw<<16)|(lsw&65535)}function rol(num,cnt){return(num<<cnt)|(num>>>(32-cnt))}function str2binb(str){var bin=[];var mask=255;for(var i=0;i<str.length*8;i+=8){bin[i>>5]|=(str.charCodeAt(i/8)&mask)<<(24-i%32)}return bin}function binb2str(bin){var str="";var mask=255;for(var i=0;i<bin.length*32;i+=8){str+=String.fromCharCode((bin[i>>5]>>>(24-i%32))&mask)}return str}function binb2b64(binarray){var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var str="";var triplet,j;for(var i=0;i<binarray.length*4;i+=3){triplet=(((binarray[i>>2]>>8*(3-i%4))&255)<<16)|(((binarray[i+1>>2]>>8*(3-(i+1)%4))&255)<<8)|((binarray[i+2>>2]>>8*(3-(i+2)%4))&255);for(j=0;j<4;j++){if(i*8+j*6>binarray.length*32){str+="="}else{str+=tab.charAt((triplet>>6*(3-j))&63)}}}return str}var MD5=(function(){var safe_add=function(x,y){var lsw=(x&65535)+(y&65535);var msw=(x>>16)+(y>>16)+(lsw>>16);return(msw<<16)|(lsw&65535)};var bit_rol=function(num,cnt){return(num<<cnt)|(num>>>(32-cnt))};var str2binl=function(str){var bin=[];for(var i=0;i<str.length*8;i+=8){bin[i>>5]|=(str.charCodeAt(i/8)&255)<<(i%32)}return bin};var binl2str=function(bin){var str="";for(var i=0;i<bin.length*32;i+=8){str+=String.fromCharCode((bin[i>>5]>>>(i%32))&255)}return str};var binl2hex=function(binarray){var hex_tab="0123456789abcdef";var str="";for(var i=0;i<binarray.length*4;i++){str+=hex_tab.charAt((binarray[i>>2]>>((i%4)*8+4))&15)+hex_tab.charAt((binarray[i>>2]>>((i%4)*8))&15)}return str};var md5_cmn=function(q,a,b,x,s,t){return safe_add(bit_rol(safe_add(safe_add(a,q),safe_add(x,t)),s),b)};var md5_ff=function(a,b,c,d,x,s,t){return md5_cmn((b&c)|((~b)&d),a,b,x,s,t)};var md5_gg=function(a,b,c,d,x,s,t){return md5_cmn((b&d)|(c&(~d)),a,b,x,s,t)};var md5_hh=function(a,b,c,d,x,s,t){return md5_cmn(b^c^d,a,b,x,s,t)};var md5_ii=function(a,b,c,d,x,s,t){return md5_cmn(c^(b|(~d)),a,b,x,s,t)};var core_md5=function(x,len){x[len>>5]|=128<<((len)%32);x[(((len+64)>>>9)<<4)+14]=len;var a=1732584193;var b=-271733879;var c=-1732584194;var d=271733878;var olda,oldb,oldc,oldd;for(var i=0;i<x.length;i+=16){olda=a;oldb=b;oldc=c;oldd=d;a=md5_ff(a,b,c,d,x[i+0],7,-680876936);d=md5_ff(d,a,b,c,x[i+1],12,-389564586);c=md5_ff(c,d,a,b,x[i+2],17,606105819);b=md5_ff(b,c,d,a,x[i+3],22,-1044525330);a=md5_ff(a,b,c,d,x[i+4],7,-176418897);d=md5_ff(d,a,b,c,x[i+5],12,1200080426);c=md5_ff(c,d,a,b,x[i+6],17,-1473231341);b=md5_ff(b,c,d,a,x[i+7],22,-45705983);a=md5_ff(a,b,c,d,x[i+8],7,1770035416);d=md5_ff(d,a,b,c,x[i+9],12,-1958414417);c=md5_ff(c,d,a,b,x[i+10],17,-42063);b=md5_ff(b,c,d,a,x[i+11],22,-1990404162);a=md5_ff(a,b,c,d,x[i+12],7,1804603682);d=md5_ff(d,a,b,c,x[i+13],12,-40341101);c=md5_ff(c,d,a,b,x[i+14],17,-1502002290);b=md5_ff(b,c,d,a,x[i+15],22,1236535329);a=md5_gg(a,b,c,d,x[i+1],5,-165796510);d=md5_gg(d,a,b,c,x[i+6],9,-1069501632);c=md5_gg(c,d,a,b,x[i+11],14,643717713);b=md5_gg(b,c,d,a,x[i+0],20,-373897302);a=md5_gg(a,b,c,d,x[i+5],5,-701558691);d=md5_gg(d,a,b,c,x[i+10],9,38016083);c=md5_gg(c,d,a,b,x[i+15],14,-660478335);b=md5_gg(b,c,d,a,x[i+4],20,-405537848);a=md5_gg(a,b,c,d,x[i+9],5,568446438);d=md5_gg(d,a,b,c,x[i+14],9,-1019803690);c=md5_gg(c,d,a,b,x[i+3],14,-187363961);b=md5_gg(b,c,d,a,x[i+8],20,1163531501);a=md5_gg(a,b,c,d,x[i+13],5,-1444681467);d=md5_gg(d,a,b,c,x[i+2],9,-51403784);c=md5_gg(c,d,a,b,x[i+7],14,1735328473);b=md5_gg(b,c,d,a,x[i+12],20,-1926607734);a=md5_hh(a,b,c,d,x[i+5],4,-378558);d=md5_hh(d,a,b,c,x[i+8],11,-2022574463);c=md5_hh(c,d,a,b,x[i+11],16,1839030562);b=md5_hh(b,c,d,a,x[i+14],23,-35309556);a=md5_hh(a,b,c,d,x[i+1],4,-1530992060);d=md5_hh(d,a,b,c,x[i+4],11,1272893353);c=md5_hh(c,d,a,b,x[i+7],16,-155497632);b=md5_hh(b,c,d,a,x[i+10],23,-1094730640);a=md5_hh(a,b,c,d,x[i+13],4,681279174);d=md5_hh(d,a,b,c,x[i+0],11,-358537222);c=md5_hh(c,d,a,b,x[i+3],16,-722521979);b=md5_hh(b,c,d,a,x[i+6],23,76029189);a=md5_hh(a,b,c,d,x[i+9],4,-640364487);d=md5_hh(d,a,b,c,x[i+12],11,-421815835);c=md5_hh(c,d,a,b,x[i+15],16,530742520);b=md5_hh(b,c,d,a,x[i+2],23,-995338651);a=md5_ii(a,b,c,d,x[i+0],6,-198630844);d=md5_ii(d,a,b,c,x[i+7],10,1126891415);c=md5_ii(c,d,a,b,x[i+14],15,-1416354905);b=md5_ii(b,c,d,a,x[i+5],21,-57434055);a=md5_ii(a,b,c,d,x[i+12],6,1700485571);d=md5_ii(d,a,b,c,x[i+3],10,-1894986606);c=md5_ii(c,d,a,b,x[i+10],15,-1051523);b=md5_ii(b,c,d,a,x[i+1],21,-2054922799);a=md5_ii(a,b,c,d,x[i+8],6,1873313359);d=md5_ii(d,a,b,c,x[i+15],10,-30611744);c=md5_ii(c,d,a,b,x[i+6],15,-1560198380);b=md5_ii(b,c,d,a,x[i+13],21,1309151649);a=md5_ii(a,b,c,d,x[i+4],6,-145523070);d=md5_ii(d,a,b,c,x[i+11],10,-1120210379);c=md5_ii(c,d,a,b,x[i+2],15,718787259);b=md5_ii(b,c,d,a,x[i+9],21,-343485551);a=safe_add(a,olda);b=safe_add(b,oldb);c=safe_add(c,oldc);d=safe_add(d,oldd)}return[a,b,c,d]};var obj={hexdigest:function(s){return binl2hex(core_md5(str2binl(s),s.length*8))},hash:function(s){return binl2str(core_md5(str2binl(s),s.length*8))}};return obj})();if(!Function.prototype.bind){Function.prototype.bind=function(obj){var func=this;var _slice=Array.prototype.slice;var _concat=Array.prototype.concat;var _args=_slice.call(arguments,1);return function(){return func.apply(obj?obj:this,_concat.call(_args,_slice.call(arguments,0)))}}}if(!Array.prototype.indexOf){Array.prototype.indexOf=function(elt){var len=this.length;var from=Number(arguments[1])||0;from=(from<0)?Math.ceil(from):Math.floor(from);if(from<0){from+=len}for(;from<len;from++){if(from in this&&this[from]===elt){return from}}return -1}}(function(callback){var Strophe;function $build(name,attrs){return new Strophe.Builder(name,attrs)}function $msg(attrs){return new Strophe.Builder("message",attrs)}function $iq(attrs){return new Strophe.Builder("iq",attrs)}function $pres(attrs){return new Strophe.Builder("presence",attrs)}Strophe={VERSION:"1.1.3",NS:{HTTPBIND:"http://jabber.org/protocol/httpbind",BOSH:"urn:xmpp:xbosh",CLIENT:"jabber:client",AUTH:"jabber:iq:auth",ROSTER:"jabber:iq:roster",PROFILE:"jabber:iq:profile",DISCO_INFO:"http://jabber.org/protocol/disco#info",DISCO_ITEMS:"http://jabber.org/protocol/disco#items",MUC:"http://jabber.org/protocol/muc",SASL:"urn:ietf:params:xml:ns:xmpp-sasl",STREAM:"http://etherx.jabber.org/streams",BIND:"urn:ietf:params:xml:ns:xmpp-bind",SESSION:"urn:ietf:params:xml:ns:xmpp-session",VERSION:"jabber:iq:version",STANZAS:"urn:ietf:params:xml:ns:xmpp-stanzas",XHTML_IM:"http://jabber.org/protocol/xhtml-im",XHTML:"http://www.w3.org/1999/xhtml"},XHTML:{tags:["a","blockquote","br","cite","em","img","li","ol","p","span","strong","ul","body"],attributes:{a:["href"],blockquote:["style"],br:[],cite:["style"],em:[],img:["src","alt","style","height","width"],li:["style"],ol:["style"],p:["style"],span:["style"],strong:[],ul:["style"],body:[]},css:["background-color","color","font-family","font-size","font-style","font-weight","margin-left","margin-right","text-align","text-decoration"],validTag:function(tag){for(var i=0;i<Strophe.XHTML.tags.length;i++){if(tag==Strophe.XHTML.tags[i]){return true}}return false},validAttribute:function(tag,attribute){if(typeof Strophe.XHTML.attributes[tag]!=="undefined"&&Strophe.XHTML.attributes[tag].length>0){for(var i=0;i<Strophe.XHTML.attributes[tag].length;i++){if(attribute==Strophe.XHTML.attributes[tag][i]){return true}}}return false},validCSS:function(style){for(var i=0;i<Strophe.XHTML.css.length;i++){if(style==Strophe.XHTML.css[i]){return true}}return false}},Status:{ERROR:0,CONNECTING:1,CONNFAIL:2,AUTHENTICATING:3,AUTHFAIL:4,CONNECTED:5,DISCONNECTED:6,DISCONNECTING:7,ATTACHED:8},LogLevel:{DEBUG:0,INFO:1,WARN:2,ERROR:3,FATAL:4},ElementType:{NORMAL:1,TEXT:3,CDATA:4,FRAGMENT:11},TIMEOUT:1.1,SECONDARY_TIMEOUT:0.1,addNamespace:function(name,value){Strophe.NS[name]=value},forEachChild:function(elem,elemName,func){var i,childNode;for(i=0;i<elem.childNodes.length;i++){childNode=elem.childNodes[i];if(childNode.nodeType==Strophe.ElementType.NORMAL&&(!elemName||this.isTagEqual(childNode,elemName))){func(childNode)}}},isTagEqual:function(el,name){return el.tagName.toLowerCase()==name.toLowerCase()},_xmlGenerator:null,_makeGenerator:function(){var doc;if(document.implementation.createDocument===undefined||document.implementation.createDocument&&document.documentMode&&document.documentMode<10){doc=this._getIEXmlDom();doc.appendChild(doc.createElement("strophe"))}else{doc=document.implementation.createDocument("jabber:client","strophe",null)}return doc},xmlGenerator:function(){if(!Strophe._xmlGenerator){Strophe._xmlGenerator=Strophe._makeGenerator()}return Strophe._xmlGenerator},_getIEXmlDom:function(){var doc=null;var docStrings=["Msxml2.DOMDocument.6.0","Msxml2.DOMDocument.5.0","Msxml2.DOMDocument.4.0","MSXML2.DOMDocument.3.0","MSXML2.DOMDocument","MSXML.DOMDocument","Microsoft.XMLDOM"];for(var d=0;d<docStrings.length;d++){if(doc===null){try{doc=new ActiveXObject(docStrings[d])}catch(e){doc=null}}else{break}}return doc},xmlElement:function(name){if(!name){return null}var node=Strophe.xmlGenerator().createElement(name);var a,i,k;for(a=1;a<arguments.length;a++){if(!arguments[a]){continue}if(typeof(arguments[a])=="string"||typeof(arguments[a])=="number"){node.appendChild(Strophe.xmlTextNode(arguments[a]))}else{if(typeof(arguments[a])=="object"&&typeof(arguments[a].sort)=="function"){for(i=0;i<arguments[a].length;i++){if(typeof(arguments[a][i])=="object"&&typeof(arguments[a][i].sort)=="function"){node.setAttribute(arguments[a][i][0],arguments[a][i][1])}}}else{if(typeof(arguments[a])=="object"){for(k in arguments[a]){if(arguments[a].hasOwnProperty(k)){node.setAttribute(k,arguments[a][k])}}}}}}return node},xmlescape:function(text){text=text.replace(/\&/g,"&amp;");text=text.replace(/</g,"&lt;");text=text.replace(/>/g,"&gt;");text=text.replace(/'/g,"&apos;");text=text.replace(/"/g,"&quot;");return text},xmlTextNode:function(text){return Strophe.xmlGenerator().createTextNode(text)},xmlHtmlNode:function(html){var node;if(window.DOMParser){var parser=new DOMParser();node=parser.parseFromString(html,"text/xml")}else{node=new ActiveXObject("Microsoft.XMLDOM");node.async="false";node.loadXML(html)}return node},getText:function(elem){if(!elem){return null}var str="";if(elem.childNodes.length===0&&elem.nodeType==Strophe.ElementType.TEXT){str+=elem.nodeValue}for(var i=0;i<elem.childNodes.length;i++){if(elem.childNodes[i].nodeType==Strophe.ElementType.TEXT){str+=elem.childNodes[i].nodeValue}}return Strophe.xmlescape(str)},copyElement:function(elem){var i,el;if(elem.nodeType==Strophe.ElementType.NORMAL){el=Strophe.xmlElement(elem.tagName);for(i=0;i<elem.attributes.length;i++){el.setAttribute(elem.attributes[i].nodeName.toLowerCase(),elem.attributes[i].value)}for(i=0;i<elem.childNodes.length;i++){el.appendChild(Strophe.copyElement(elem.childNodes[i]))}}else{if(elem.nodeType==Strophe.ElementType.TEXT){el=Strophe.xmlGenerator().createTextNode(elem.nodeValue)}}return el},createHtml:function(elem){var i,el,j,tag,attribute,value,css,cssAttrs,attr,cssName,cssValue;if(elem.nodeType==Strophe.ElementType.NORMAL){tag=elem.nodeName.toLowerCase();if(Strophe.XHTML.validTag(tag)){try{el=Strophe.xmlElement(tag);for(i=0;i<Strophe.XHTML.attributes[tag].length;i++){attribute=Strophe.XHTML.attributes[tag][i];value=elem.getAttribute(attribute);if(typeof value=="undefined"||value===null||value===""||value===false||value===0){continue}if(attribute=="style"&&typeof value=="object"){if(typeof value.cssText!="undefined"){value=value.cssText}}if(attribute=="style"){css=[];cssAttrs=value.split(";");for(j=0;j<cssAttrs.length;j++){attr=cssAttrs[j].split(":");cssName=attr[0].replace(/^\s*/,"").replace(/\s*$/,"").toLowerCase();if(Strophe.XHTML.validCSS(cssName)){cssValue=attr[1].replace(/^\s*/,"").replace(/\s*$/,"");css.push(cssName+": "+cssValue)}}if(css.length>0){value=css.join("; ");el.setAttribute(attribute,value)}}else{el.setAttribute(attribute,value)}}for(i=0;i<elem.childNodes.length;i++){el.appendChild(Strophe.createHtml(elem.childNodes[i]))}}catch(e){el=Strophe.xmlTextNode("")}}else{el=Strophe.xmlGenerator().createDocumentFragment();for(i=0;i<elem.childNodes.length;i++){el.appendChild(Strophe.createHtml(elem.childNodes[i]))}}}else{if(elem.nodeType==Strophe.ElementType.FRAGMENT){el=Strophe.xmlGenerator().createDocumentFragment();for(i=0;i<elem.childNodes.length;i++){el.appendChild(Strophe.createHtml(elem.childNodes[i]))}}else{if(elem.nodeType==Strophe.ElementType.TEXT){el=Strophe.xmlTextNode(elem.nodeValue)}}}return el},escapeNode:function(node){return node.replace(/^\s+|\s+$/g,"").replace(/\\/g,"\\5c").replace(/ /g,"\\20").replace(/\"/g,"\\22").replace(/\&/g,"\\26").replace(/\'/g,"\\27").replace(/\//g,"\\2f").replace(/:/g,"\\3a").replace(/</g,"\\3c").replace(/>/g,"\\3e").replace(/@/g,"\\40")},unescapeNode:function(node){return node.replace(/\\20/g," ").replace(/\\22/g,'"').replace(/\\26/g,"&").replace(/\\27/g,"'").replace(/\\2f/g,"/").replace(/\\3a/g,":").replace(/\\3c/g,"<").replace(/\\3e/g,">").replace(/\\40/g,"@").replace(/\\5c/g,"\\")},getNodeFromJid:function(jid){if(jid.indexOf("@")<0){return null}return jid.split("@")[0]},getDomainFromJid:function(jid){var bare=Strophe.getBareJidFromJid(jid);if(bare.indexOf("@")<0){return bare}else{var parts=bare.split("@");parts.splice(0,1);return parts.join("@")}},getResourceFromJid:function(jid){var s=jid.split("/");if(s.length<2){return null}s.splice(0,1);return s.join("/")},getBareJidFromJid:function(jid){return jid?jid.split("/")[0]:null},log:function(level,msg){return},debug:function(msg){this.log(this.LogLevel.DEBUG,msg)},info:function(msg){this.log(this.LogLevel.INFO,msg)},warn:function(msg){this.log(this.LogLevel.WARN,msg)},error:function(msg){this.log(this.LogLevel.ERROR,msg)},fatal:function(msg){this.log(this.LogLevel.FATAL,msg)},serialize:function(elem){var result;if(!elem){return null}if(typeof(elem.tree)==="function"){elem=elem.tree()}var nodeName=elem.nodeName;var i,child;if(elem.getAttribute("_realname")){nodeName=elem.getAttribute("_realname")}result="<"+nodeName;for(i=0;i<elem.attributes.length;i++){if(elem.attributes[i].nodeName!="_realname"){result+=" "+elem.attributes[i].nodeName.toLowerCase()+"='"+elem.attributes[i].value.replace(/&/g,"&amp;").replace(/\'/g,"&apos;").replace(/>/g,"&gt;").replace(/</g,"&lt;")+"'"}}if(elem.childNodes.length>0){result+=">";for(i=0;i<elem.childNodes.length;i++){child=elem.childNodes[i];switch(child.nodeType){case Strophe.ElementType.NORMAL:result+=Strophe.serialize(child);break;case Strophe.ElementType.TEXT:result+=Strophe.xmlescape(child.nodeValue);break;case Strophe.ElementType.CDATA:result+="<![CDATA["+child.nodeValue+"]]>"}}result+="</"+nodeName+">"}else{result+="/>"}return result},_requestId:0,_connectionPlugins:{},addConnectionPlugin:function(name,ptype){Strophe._connectionPlugins[name]=ptype}};Strophe.Builder=function(name,attrs){if(name=="presence"||name=="message"||name=="iq"){if(attrs&&!attrs.xmlns){attrs.xmlns=Strophe.NS.CLIENT}else{if(!attrs){attrs={xmlns:Strophe.NS.CLIENT}}}}this.nodeTree=Strophe.xmlElement(name,attrs);this.node=this.nodeTree};Strophe.Builder.prototype={tree:function(){return this.nodeTree},toString:function(){return Strophe.serialize(this.nodeTree)},up:function(){this.node=this.node.parentNode;return this},attrs:function(moreattrs){for(var k in moreattrs){if(moreattrs.hasOwnProperty(k)){this.node.setAttribute(k,moreattrs[k])}}return this},c:function(name,attrs,text){var child=Strophe.xmlElement(name,attrs,text);this.node.appendChild(child);if(!text){this.node=child}return this},cnode:function(elem){var impNode;var xmlGen=Strophe.xmlGenerator();try{impNode=(xmlGen.importNode!==undefined)}catch(e){impNode=false}var newElem=impNode?xmlGen.importNode(elem,true):Strophe.copyElement(elem);this.node.appendChild(newElem);this.node=newElem;return this},t:function(text){var child=Strophe.xmlTextNode(text);this.node.appendChild(child);return this},h:function(html){var fragment=document.createElement("body");fragment.innerHTML=html;var xhtml=Strophe.createHtml(fragment);while(xhtml.childNodes.length>0){this.node.appendChild(xhtml.childNodes[0])}return this}};Strophe.Handler=function(handler,ns,name,type,id,from,options){this.handler=handler;this.ns=ns;this.name=name;this.type=type;this.id=id;this.options=options||{matchBare:false};if(!this.options.matchBare){this.options.matchBare=false}if(this.options.matchBare){this.from=from?Strophe.getBareJidFromJid(from):null}else{this.from=from}this.user=true};Strophe.Handler.prototype={isMatch:function(elem){var nsMatch;var from=null;if(this.options.matchBare){from=Strophe.getBareJidFromJid(elem.getAttribute("from"))}else{from=elem.getAttribute("from")}nsMatch=false;if(!this.ns){nsMatch=true}else{var that=this;Strophe.forEachChild(elem,null,function(elem){if(elem.getAttribute("xmlns")==that.ns){nsMatch=true}});nsMatch=nsMatch||elem.getAttribute("xmlns")==this.ns}if(nsMatch&&(!this.name||Strophe.isTagEqual(elem,this.name))&&(!this.type||elem.getAttribute("type")==this.type)&&(!this.id||elem.getAttribute("id")==this.id)&&(!this.from||from==this.from)){return true}return false},run:function(elem){var result=null;try{result=this.handler(elem)}catch(e){if(e.sourceURL){Strophe.fatal("error: "+this.handler+" "+e.sourceURL+":"+e.line+" - "+e.name+": "+e.message)}else{if(e.fileName){if(typeof(console)!="undefined"){console.trace();console.error(this.handler," - error - ",e,e.message)}Strophe.fatal("error: "+this.handler+" "+e.fileName+":"+e.lineNumber+" - "+e.name+": "+e.message)}else{Strophe.fatal("error: "+e.message+"\n"+e.stack)}}throw e}return result},toString:function(){return"{Handler: "+this.handler+"("+this.name+","+this.id+","+this.ns+")}"}};Strophe.TimedHandler=function(period,handler){this.period=period;this.handler=handler;this.lastCalled=new Date().getTime();this.user=true};Strophe.TimedHandler.prototype={run:function(){this.lastCalled=new Date().getTime();return this.handler()},reset:function(){this.lastCalled=new Date().getTime()},toString:function(){return"{TimedHandler: "+this.handler+"("+this.period+")}"}};Strophe.Connection=function(service,options){this.service=service;this.options=options||{};var proto=this.options.protocol||"";if(service.indexOf("ws:")===0||service.indexOf("wss:")===0||proto.indexOf("ws")===0){this._proto=new Strophe.Websocket(this)}else{this._proto=new Strophe.Bosh(this)}this.jid="";this.domain=null;this.features=null;this._sasl_data={};this.do_session=false;this.do_bind=false;this.timedHandlers=[];this.handlers=[];this.removeTimeds=[];this.removeHandlers=[];this.addTimeds=[];this.addHandlers=[];this._authentication={};this._idleTimeout=null;this._disconnectTimeout=null;this.do_authentication=true;this.authenticated=false;this.disconnecting=false;this.connected=false;this.errors=0;this.paused=false;this._data=[];this._uniqueId=0;this._sasl_success_handler=null;this._sasl_failure_handler=null;this._sasl_challenge_handler=null;this.maxRetries=5;this._idleTimeout=setTimeout(this._onIdle.bind(this),100);for(var k in Strophe._connectionPlugins){if(Strophe._connectionPlugins.hasOwnProperty(k)){var ptype=Strophe._connectionPlugins[k];var F=function(){};F.prototype=ptype;this[k]=new F();this[k].init(this)}}};Strophe.Connection.prototype={reset:function(){this._proto._reset();this.do_session=false;this.do_bind=false;this.timedHandlers=[];this.handlers=[];this.removeTimeds=[];this.removeHandlers=[];this.addTimeds=[];this.addHandlers=[];this._authentication={};this.authenticated=false;this.disconnecting=false;this.connected=false;this.errors=0;this._requests=[];this._uniqueId=0},pause:function(){this.paused=true},resume:function(){this.paused=false},getUniqueId:function(suffix){if(typeof(suffix)=="string"||typeof(suffix)=="number"){return ++this._uniqueId+":"+suffix}else{return ++this._uniqueId+""}},connect:function(jid,pass,callback,wait,hold,route){this.jid=jid;this.authzid=Strophe.getBareJidFromJid(this.jid);this.authcid=Strophe.getNodeFromJid(this.jid);this.pass=pass;this.servtype="xmpp";this.connect_callback=callback;this.disconnecting=false;this.connected=false;this.authenticated=false;this.errors=0;this.domain=Strophe.getDomainFromJid(this.jid);this._changeConnectStatus(Strophe.Status.CONNECTING,null);this._proto._connect(wait,hold,route)},attach:function(jid,sid,rid,callback,wait,hold,wind){this._proto._attach(jid,sid,rid,callback,wait,hold,wind)},xmlInput:function(elem){return},xmlOutput:function(elem){return},rawInput:function(data){return},rawOutput:function(data){return},send:function(elem){if(elem===null){return}if(typeof(elem.sort)==="function"){for(var i=0;i<elem.length;i++){this._queueData(elem[i])}}else{if(typeof(elem.tree)==="function"){this._queueData(elem.tree())}else{this._queueData(elem)}}this._proto._send()},flush:function(){clearTimeout(this._idleTimeout);this._onIdle()},sendIQ:function(elem,callback,errback,timeout){var timeoutHandler=null;var that=this;if(typeof(elem.tree)==="function"){elem=elem.tree()}var id=elem.getAttribute("id");if(!id){id=this.getUniqueId("sendIQ");elem.setAttribute("id",id)}var handler=this.addHandler(function(stanza){if(timeoutHandler){that.deleteTimedHandler(timeoutHandler)}var iqtype=stanza.getAttribute("type");if(iqtype=="result"){if(callback){callback(stanza)}}else{if(iqtype=="error"){if(errback){errback(stanza)}}else{throw {name:"StropheError",message:"Got bad IQ type of "+iqtype}}}},null,"iq",null,id);if(timeout){timeoutHandler=this.addTimedHandler(timeout,function(){that.deleteHandler(handler);if(errback){errback(null)}return false})}this.send(elem);return id},_queueData:function(element){if(element===null||!element.tagName||!element.childNodes){throw {name:"StropheError",message:"Cannot queue non-DOMElement."}}this._data.push(element)},_sendRestart:function(){this._data.push("restart");this._proto._sendRestart();this._idleTimeout=setTimeout(this._onIdle.bind(this),100)},addTimedHandler:function(period,handler){var thand=new Strophe.TimedHandler(period,handler);this.addTimeds.push(thand);return thand},deleteTimedHandler:function(handRef){this.removeTimeds.push(handRef)},addHandler:function(handler,ns,name,type,id,from,options){var hand=new Strophe.Handler(handler,ns,name,type,id,from,options);this.addHandlers.push(hand);return hand},deleteHandler:function(handRef){this.removeHandlers.push(handRef)},disconnect:function(reason){this._changeConnectStatus(Strophe.Status.DISCONNECTING,reason);Strophe.info("Disconnect was called because: "+reason);if(this.connected){var pres=false;this.disconnecting=true;if(this.authenticated){pres=$pres({xmlns:Strophe.NS.CLIENT,type:"unavailable"})}this._disconnectTimeout=this._addSysTimedHandler(3000,this._onDisconnectTimeout.bind(this));this._proto._disconnect(pres)}},_changeConnectStatus:function(status,condition){for(var k in Strophe._connectionPlugins){if(Strophe._connectionPlugins.hasOwnProperty(k)){var plugin=this[k];if(plugin.statusChanged){try{plugin.statusChanged(status,condition)}catch(err){Strophe.error(""+k+" plugin caused an exception changing status: "+err)}}}}if(this.connect_callback){try{this.connect_callback(status,condition)}catch(e){Strophe.error("User connection callback caused an exception: "+e)}}},_doDisconnect:function(){if(this._disconnectTimeout!==null){this.deleteTimedHandler(this._disconnectTimeout);this._disconnectTimeout=null}Strophe.info("_doDisconnect was called");this._proto._doDisconnect();this.authenticated=false;this.disconnecting=false;this.handlers=[];this.timedHandlers=[];this.removeTimeds=[];this.removeHandlers=[];this.addTimeds=[];this.addHandlers=[];this._changeConnectStatus(Strophe.Status.DISCONNECTED,null);this.connected=false},_dataRecv:function(req,raw){Strophe.info("_dataRecv called");var elem=this._proto._reqToData(req);if(elem===null){return}if(this.xmlInput!==Strophe.Connection.prototype.xmlInput){if(elem.nodeName===this._proto.strip&&elem.childNodes.length){this.xmlInput(elem.childNodes[0])}else{this.xmlInput(elem)}}if(this.rawInput!==Strophe.Connection.prototype.rawInput){if(raw){this.rawInput(raw)}else{this.rawInput(Strophe.serialize(elem))}}var i,hand;while(this.removeHandlers.length>0){hand=this.removeHandlers.pop();i=this.handlers.indexOf(hand);if(i>=0){this.handlers.splice(i,1)}}while(this.addHandlers.length>0){this.handlers.push(this.addHandlers.pop())}if(this.disconnecting&&this._proto._emptyQueue()){this._doDisconnect();return}var typ=elem.getAttribute("type");var cond,conflict;if(typ!==null&&typ=="terminate"){if(this.disconnecting){return}cond=elem.getAttribute("condition");conflict=elem.getElementsByTagName("conflict");if(cond!==null){if(cond=="remote-stream-error"&&conflict.length>0){cond="conflict"}this._changeConnectStatus(Strophe.Status.CONNFAIL,cond)}else{this._changeConnectStatus(Strophe.Status.CONNFAIL,"unknown")}this.disconnect("unknown stream-error");return}var that=this;Strophe.forEachChild(elem,null,function(child){var i,newList;newList=that.handlers;that.handlers=[];for(i=0;i<newList.length;i++){var hand=newList[i];try{if(hand.isMatch(child)&&(that.authenticated||!hand.user)){if(hand.run(child)){that.handlers.push(hand)}}else{that.handlers.push(hand)}}catch(e){Strophe.warn("Removing Strophe handlers due to uncaught exception: "+e.message)}}})},mechanisms:{},_connect_cb:function(req,_callback,raw){Strophe.info("_connect_cb was called");this.connected=true;var bodyWrap=this._proto._reqToData(req);if(!bodyWrap){return}if(this.xmlInput!==Strophe.Connection.prototype.xmlInput){if(bodyWrap.nodeName===this._proto.strip&&bodyWrap.childNodes.length){this.xmlInput(bodyWrap.childNodes[0])}else{this.xmlInput(bodyWrap)}}if(this.rawInput!==Strophe.Connection.prototype.rawInput){if(raw){this.rawInput(raw)}else{this.rawInput(Strophe.serialize(bodyWrap))}}var conncheck=this._proto._connect_cb(bodyWrap);if(conncheck===Strophe.Status.CONNFAIL){return}this._authentication.sasl_scram_sha1=false;this._authentication.sasl_plain=false;this._authentication.sasl_digest_md5=false;this._authentication.sasl_anonymous=false;this._authentication.legacy_auth=false;var hasFeatures=bodyWrap.getElementsByTagName("stream:features").length>0;if(!hasFeatures){hasFeatures=bodyWrap.getElementsByTagName("features").length>0}var mechanisms=bodyWrap.getElementsByTagName("mechanism");var matched=[];var i,mech,found_authentication=false;if(!hasFeatures){this._proto._no_auth_received(_callback);return}if(mechanisms.length>0){for(i=0;i<mechanisms.length;i++){mech=Strophe.getText(mechanisms[i]);if(this.mechanisms[mech]){matched.push(this.mechanisms[mech])}}}this._authentication.legacy_auth=bodyWrap.getElementsByTagName("auth").length>0;found_authentication=this._authentication.legacy_auth||matched.length>0;if(!found_authentication){this._proto._no_auth_received(_callback);return}if(this.do_authentication!==false){this.authenticate(matched)}},authenticate:function(matched){var i;for(i=0;i<matched.length-1;++i){var higher=i;for(var j=i+1;j<matched.length;++j){if(matched[j].prototype.priority>matched[higher].prototype.priority){higher=j}}if(higher!=i){var swap=matched[i];matched[i]=matched[higher];matched[higher]=swap}}var mechanism_found=false;for(i=0;i<matched.length;++i){if(!matched[i].test(this)){continue}this._sasl_success_handler=this._addSysHandler(this._sasl_success_cb.bind(this),null,"success",null,null);this._sasl_failure_handler=this._addSysHandler(this._sasl_failure_cb.bind(this),null,"failure",null,null);this._sasl_challenge_handler=this._addSysHandler(this._sasl_challenge_cb.bind(this),null,"challenge",null,null);this._sasl_mechanism=new matched[i]();this._sasl_mechanism.onStart(this);var request_auth_exchange=$build("auth",{xmlns:Strophe.NS.SASL,mechanism:this._sasl_mechanism.name});if(this._sasl_mechanism.isClientFirst){var response=this._sasl_mechanism.onChallenge(this,null);request_auth_exchange.t(Base64.encode(response))}this.send(request_auth_exchange.tree());mechanism_found=true;break}if(!mechanism_found){if(Strophe.getNodeFromJid(this.jid)===null){this._changeConnectStatus(Strophe.Status.CONNFAIL,"x-strophe-bad-non-anon-jid");this.disconnect("x-strophe-bad-non-anon-jid")}else{this._changeConnectStatus(Strophe.Status.AUTHENTICATING,null);this._addSysHandler(this._auth1_cb.bind(this),null,null,null,"_auth_1");this.send($iq({type:"get",to:this.domain,id:"_auth_1"}).c("query",{xmlns:Strophe.NS.AUTH}).c("username",{}).t(Strophe.getNodeFromJid(this.jid)).tree())}}},_sasl_challenge_cb:function(elem){var challenge=Base64.decode(Strophe.getText(elem));var response=this._sasl_mechanism.onChallenge(this,challenge);var stanza=$build("response",{xmlns:Strophe.NS.SASL});if(response!==""){stanza.t(Base64.encode(response))}this.send(stanza.tree());return true},_auth1_cb:function(elem){var iq=$iq({type:"set",id:"_auth_2"}).c("query",{xmlns:Strophe.NS.AUTH}).c("username",{}).t(Strophe.getNodeFromJid(this.jid)).up().c("password").t(this.pass);if(!Strophe.getResourceFromJid(this.jid)){this.jid=Strophe.getBareJidFromJid(this.jid)+"/strophe"}iq.up().c("resource",{}).t(Strophe.getResourceFromJid(this.jid));this._addSysHandler(this._auth2_cb.bind(this),null,null,null,"_auth_2");this.send(iq.tree());return false},_sasl_success_cb:function(elem){if(this._sasl_data["server-signature"]){var serverSignature;var success=Base64.decode(Strophe.getText(elem));var attribMatch=/([a-z]+)=([^,]+)(,|$)/;var matches=success.match(attribMatch);if(matches[1]=="v"){serverSignature=matches[2]}if(serverSignature!=this._sasl_data["server-signature"]){this.deleteHandler(this._sasl_failure_handler);this._sasl_failure_handler=null;if(this._sasl_challenge_handler){this.deleteHandler(this._sasl_challenge_handler);this._sasl_challenge_handler=null}this._sasl_data={};return this._sasl_failure_cb(null)}}Strophe.info("SASL authentication succeeded.");if(this._sasl_mechanism){this._sasl_mechanism.onSuccess()}this.deleteHandler(this._sasl_failure_handler);this._sasl_failure_handler=null;if(this._sasl_challenge_handler){this.deleteHandler(this._sasl_challenge_handler);this._sasl_challenge_handler=null}this._addSysHandler(this._sasl_auth1_cb.bind(this),null,"stream:features",null,null);this._sendRestart();return false},_sasl_auth1_cb:function(elem){this.features=elem;var i,child;for(i=0;i<elem.childNodes.length;i++){child=elem.childNodes[i];if(child.nodeName=="bind"){this.do_bind=true}if(child.nodeName=="session"){this.do_session=true}}if(!this.do_bind){this._changeConnectStatus(Strophe.Status.AUTHFAIL,null);return false}else{this._addSysHandler(this._sasl_bind_cb.bind(this),null,null,null,"_bind_auth_2");var resource=Strophe.getResourceFromJid(this.jid);if(resource){this.send($iq({type:"set",id:"_bind_auth_2"}).c("bind",{xmlns:Strophe.NS.BIND}).c("resource",{}).t(resource).tree())}else{this.send($iq({type:"set",id:"_bind_auth_2"}).c("bind",{xmlns:Strophe.NS.BIND}).tree())}}return false},_sasl_bind_cb:function(elem){if(elem.getAttribute("type")=="error"){Strophe.info("SASL binding failed.");var conflict=elem.getElementsByTagName("conflict"),condition;if(conflict.length>0){condition="conflict"}this._changeConnectStatus(Strophe.Status.AUTHFAIL,condition);return false}var bind=elem.getElementsByTagName("bind");var jidNode;if(bind.length>0){jidNode=bind[0].getElementsByTagName("jid");if(jidNode.length>0){this.jid=Strophe.getText(jidNode[0]);if(this.do_session){this._addSysHandler(this._sasl_session_cb.bind(this),null,null,null,"_session_auth_2");this.send($iq({type:"set",id:"_session_auth_2"}).c("session",{xmlns:Strophe.NS.SESSION}).tree())}else{this.authenticated=true;this._changeConnectStatus(Strophe.Status.CONNECTED,null)}}}else{Strophe.info("SASL binding failed.");this._changeConnectStatus(Strophe.Status.AUTHFAIL,null);return false}},_sasl_session_cb:function(elem){if(elem.getAttribute("type")=="result"){this.authenticated=true;this._changeConnectStatus(Strophe.Status.CONNECTED,null)}else{if(elem.getAttribute("type")=="error"){Strophe.info("Session creation failed.");this._changeConnectStatus(Strophe.Status.AUTHFAIL,null);return false}}return false},_sasl_failure_cb:function(elem){if(this._sasl_success_handler){this.deleteHandler(this._sasl_success_handler);this._sasl_success_handler=null}if(this._sasl_challenge_handler){this.deleteHandler(this._sasl_challenge_handler);this._sasl_challenge_handler=null}if(this._sasl_mechanism){this._sasl_mechanism.onFailure()}this._changeConnectStatus(Strophe.Status.AUTHFAIL,null);return false},_auth2_cb:function(elem){if(elem.getAttribute("type")=="result"){this.authenticated=true;this._changeConnectStatus(Strophe.Status.CONNECTED,null)}else{if(elem.getAttribute("type")=="error"){this._changeConnectStatus(Strophe.Status.AUTHFAIL,null);this.disconnect("authentication failed")}}return false},_addSysTimedHandler:function(period,handler){var thand=new Strophe.TimedHandler(period,handler);thand.user=false;this.addTimeds.push(thand);return thand},_addSysHandler:function(handler,ns,name,type,id){var hand=new Strophe.Handler(handler,ns,name,type,id);hand.user=false;this.addHandlers.push(hand);return hand},_onDisconnectTimeout:function(){Strophe.info("_onDisconnectTimeout was called");this._proto._onDisconnectTimeout();this._doDisconnect();return false},_onIdle:function(){var i,thand,since,newList;while(this.addTimeds.length>0){this.timedHandlers.push(this.addTimeds.pop())}while(this.removeTimeds.length>0){thand=this.removeTimeds.pop();i=this.timedHandlers.indexOf(thand);if(i>=0){this.timedHandlers.splice(i,1)}}var now=new Date().getTime();newList=[];for(i=0;i<this.timedHandlers.length;i++){thand=this.timedHandlers[i];if(this.authenticated||!thand.user){since=thand.lastCalled+thand.period;if(since-now<=0){if(thand.run()){newList.push(thand)}}else{newList.push(thand)}}}this.timedHandlers=newList;clearTimeout(this._idleTimeout);this._proto._onIdle();if(this.connected){this._idleTimeout=setTimeout(this._onIdle.bind(this),100)}}};if(callback){callback(Strophe,$build,$msg,$iq,$pres)}Strophe.SASLMechanism=function(name,isClientFirst,priority){this.name=name;this.isClientFirst=isClientFirst;this.priority=priority};Strophe.SASLMechanism.prototype={test:function(connection){return true},onStart:function(connection){this._connection=connection},onChallenge:function(connection,challenge){throw new Error("You should implement challenge handling!")},onFailure:function(){this._connection=null},onSuccess:function(){this._connection=null}};Strophe.SASLAnonymous=function(){};Strophe.SASLAnonymous.prototype=new Strophe.SASLMechanism("ANONYMOUS",false,10);Strophe.SASLAnonymous.test=function(connection){return connection.authcid===null};Strophe.Connection.prototype.mechanisms[Strophe.SASLAnonymous.prototype.name]=Strophe.SASLAnonymous;Strophe.SASLPlain=function(){};Strophe.SASLPlain.prototype=new Strophe.SASLMechanism("PLAIN",true,20);Strophe.SASLPlain.test=function(connection){return connection.authcid!==null};Strophe.SASLPlain.prototype.onChallenge=function(connection){var auth_str=connection.authzid;auth_str=auth_str+"\u0000";auth_str=auth_str+connection.authcid;auth_str=auth_str+"\u0000";auth_str=auth_str+connection.pass;return auth_str};Strophe.Connection.prototype.mechanisms[Strophe.SASLPlain.prototype.name]=Strophe.SASLPlain;Strophe.SASLSHA1=function(){};Strophe.SASLSHA1.prototype=new Strophe.SASLMechanism("SCRAM-SHA-1",true,40);Strophe.SASLSHA1.test=function(connection){return connection.authcid!==null};Strophe.SASLSHA1.prototype.onChallenge=function(connection,challenge,test_cnonce){var cnonce=test_cnonce||MD5.hexdigest(Math.random()*1234567890);var auth_str="n="+connection.authcid;auth_str+=",r=";auth_str+=cnonce;connection._sasl_data.cnonce=cnonce;connection._sasl_data["client-first-message-bare"]=auth_str;auth_str="n,,"+auth_str;this.onChallenge=function(connection,challenge){var nonce,salt,iter,Hi,U,U_old,i,k;var clientKey,serverKey,clientSignature;var responseText="c=biws,";var authMessage=connection._sasl_data["client-first-message-bare"]+","+challenge+",";var cnonce=connection._sasl_data.cnonce;var attribMatch=/([a-z]+)=([^,]+)(,|$)/;while(challenge.match(attribMatch)){var matches=challenge.match(attribMatch);challenge=challenge.replace(matches[0],"");switch(matches[1]){case"r":nonce=matches[2];break;case"s":salt=matches[2];break;case"i":iter=matches[2];break}}if(nonce.substr(0,cnonce.length)!==cnonce){connection._sasl_data={};return connection._sasl_failure_cb()}responseText+="r="+nonce;authMessage+=responseText;salt=Base64.decode(salt);salt+="\x00\x00\x00\x01";Hi=U_old=core_hmac_sha1(connection.pass,salt);for(i=1;i<iter;i++){U=core_hmac_sha1(connection.pass,binb2str(U_old));for(k=0;k<5;k++){Hi[k]^=U[k]}U_old=U}Hi=binb2str(Hi);clientKey=core_hmac_sha1(Hi,"Client Key");serverKey=str_hmac_sha1(Hi,"Server Key");clientSignature=core_hmac_sha1(str_sha1(binb2str(clientKey)),authMessage);connection._sasl_data["server-signature"]=b64_hmac_sha1(serverKey,authMessage);for(k=0;k<5;k++){clientKey[k]^=clientSignature[k]}responseText+=",p="+Base64.encode(binb2str(clientKey));return responseText}.bind(this);return auth_str};Strophe.Connection.prototype.mechanisms[Strophe.SASLSHA1.prototype.name]=Strophe.SASLSHA1;Strophe.SASLMD5=function(){};Strophe.SASLMD5.prototype=new Strophe.SASLMechanism("DIGEST-MD5",false,30);Strophe.SASLMD5.test=function(connection){return connection.authcid!==null};Strophe.SASLMD5.prototype._quote=function(str){return'"'+str.replace(/\\/g,"\\\\").replace(/"/g,'\\"')+'"'};Strophe.SASLMD5.prototype.onChallenge=function(connection,challenge,test_cnonce){var attribMatch=/([a-z]+)=("[^"]+"|[^,"]+)(?:,|$)/;var cnonce=test_cnonce||MD5.hexdigest(""+(Math.random()*1234567890));var realm="";var host=null;var nonce="";var qop="";var matches;while(challenge.match(attribMatch)){matches=challenge.match(attribMatch);challenge=challenge.replace(matches[0],"");matches[2]=matches[2].replace(/^"(.+)"$/,"$1");switch(matches[1]){case"realm":realm=matches[2];break;case"nonce":nonce=matches[2];break;case"qop":qop=matches[2];break;case"host":host=matches[2];break}}var digest_uri=connection.servtype+"/"+connection.domain;if(host!==null){digest_uri=digest_uri+"/"+host}var A1=MD5.hash(connection.authcid+":"+realm+":"+this._connection.pass)+":"+nonce+":"+cnonce;var A2="AUTHENTICATE:"+digest_uri;var responseText="";responseText+="charset=utf-8,";responseText+="username="+this._quote(connection.authcid)+",";responseText+="realm="+this._quote(realm)+",";responseText+="nonce="+this._quote(nonce)+",";responseText+="nc=00000001,";responseText+="cnonce="+this._quote(cnonce)+",";responseText+="digest-uri="+this._quote(digest_uri)+",";responseText+="response="+MD5.hexdigest(MD5.hexdigest(A1)+":"+nonce+":00000001:"+cnonce+":auth:"+MD5.hexdigest(A2))+",";responseText+="qop=auth";this.onChallenge=function(){return""}.bind(this);return responseText};Strophe.Connection.prototype.mechanisms[Strophe.SASLMD5.prototype.name]=Strophe.SASLMD5})(function(){window.Strophe=arguments[0];window.$build=arguments[1];window.$msg=arguments[2];window.$iq=arguments[3];window.$pres=arguments[4]});Strophe.Request=function(elem,func,rid,sends){this.id=++Strophe._requestId;this.xmlData=elem;this.data=Strophe.serialize(elem);this.origFunc=func;this.func=func;this.rid=rid;this.date=NaN;this.sends=sends||0;this.abort=false;this.dead=null;this.age=function(){if(!this.date){return 0}var now=new Date();return(now-this.date)/1000};this.timeDead=function(){if(!this.dead){return 0}var now=new Date();return(now-this.dead)/1000};this.xhr=this._newXHR()};Strophe.Request.prototype={getResponse:function(){var node=null;if(this.xhr.responseXML&&this.xhr.responseXML.documentElement){node=this.xhr.responseXML.documentElement;if(node.tagName=="parsererror"){Strophe.error("invalid response received");Strophe.error("responseText: "+this.xhr.responseText);Strophe.error("responseXML: "+Strophe.serialize(this.xhr.responseXML));throw"parsererror"}}else{if(this.xhr.responseText){Strophe.error("invalid response received");Strophe.error("responseText: "+this.xhr.responseText);Strophe.error("responseXML: "+Strophe.serialize(this.xhr.responseXML))}}return node},_newXHR:function(){var xhr=null;if(window.XMLHttpRequest){xhr=new XMLHttpRequest();if(xhr.overrideMimeType){xhr.overrideMimeType("text/xml")}}else{if(window.ActiveXObject){xhr=new ActiveXObject("Microsoft.XMLHTTP")}}xhr.onreadystatechange=this.func.bind(null,this);return xhr}};Strophe.Bosh=function(connection){this._conn=connection;this.rid=Math.floor(Math.random()*4294967295);this.sid=null;this.hold=1;this.wait=60;this.window=5;this._requests=[]};Strophe.Bosh.prototype={strip:null,_buildBody:function(){var bodyWrap=$build("body",{rid:this.rid++,xmlns:Strophe.NS.HTTPBIND});if(this.sid!==null){bodyWrap.attrs({sid:this.sid})}return bodyWrap},_reset:function(){this.rid=Math.floor(Math.random()*4294967295);this.sid=null},_connect:function(wait,hold,route){this.wait=wait||this.wait;this.hold=hold||this.hold;var body=this._buildBody().attrs({to:this._conn.domain,"xml:lang":"en",wait:this.wait,hold:this.hold,content:"text/xml; charset=utf-8",ver:"1.6","xmpp:version":"1.0","xmlns:xmpp":Strophe.NS.BOSH});if(route){body.attrs({route:route})}var _connect_cb=this._conn._connect_cb;this._requests.push(new Strophe.Request(body.tree(),this._onRequestStateChange.bind(this,_connect_cb.bind(this._conn)),body.tree().getAttribute("rid")));this._throttledRequestHandler()},_attach:function(jid,sid,rid,callback,wait,hold,wind){this._conn.jid=jid;this.sid=sid;this.rid=rid;this._conn.connect_callback=callback;this._conn.domain=Strophe.getDomainFromJid(this._conn.jid);this._conn.authenticated=true;this._conn.connected=true;this.wait=wait||this.wait;this.hold=hold||this.hold;this.window=wind||this.window;this._conn._changeConnectStatus(Strophe.Status.ATTACHED,null)},_connect_cb:function(bodyWrap){var typ=bodyWrap.getAttribute("type");var cond,conflict;if(typ!==null&&typ=="terminate"){Strophe.error("BOSH-Connection failed: "+cond);cond=bodyWrap.getAttribute("condition");conflict=bodyWrap.getElementsByTagName("conflict");if(cond!==null){if(cond=="remote-stream-error"&&conflict.length>0){cond="conflict"}this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,cond)}else{this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"unknown")}this._conn._doDisconnect();return Strophe.Status.CONNFAIL}if(!this.sid){this.sid=bodyWrap.getAttribute("sid")}var wind=bodyWrap.getAttribute("requests");if(wind){this.window=parseInt(wind,10)}var hold=bodyWrap.getAttribute("hold");if(hold){this.hold=parseInt(hold,10)}var wait=bodyWrap.getAttribute("wait");if(wait){this.wait=parseInt(wait,10)}},_disconnect:function(pres){this._sendTerminate(pres)},_doDisconnect:function(){this.sid=null;this.rid=Math.floor(Math.random()*4294967295)},_emptyQueue:function(){return this._requests.length===0},_hitError:function(reqStatus){this.errors++;Strophe.warn("request errored, status: "+reqStatus+", number of errors: "+this.errors);if(this.errors>4){this._onDisconnectTimeout()}},_no_auth_received:function(_callback){if(_callback){_callback=_callback.bind(this._conn)}else{_callback=this._conn._connect_cb.bind(this._conn)}var body=this._buildBody();this._requests.push(new Strophe.Request(body.tree(),this._onRequestStateChange.bind(this,_callback.bind(this._conn)),body.tree().getAttribute("rid")));this._throttledRequestHandler()},_onDisconnectTimeout:function(){var req;while(this._requests.length>0){req=this._requests.pop();req.abort=true;req.xhr.abort();req.xhr.onreadystatechange=function(){}}},_onIdle:function(){var data=this._conn._data;if(this._conn.authenticated&&this._requests.length===0&&data.length===0&&!this._conn.disconnecting){Strophe.info("no requests during idle cycle, sending blank request");data.push(null)}if(this._requests.length<2&&data.length>0&&!this._conn.paused){var body=this._buildBody();for(var i=0;i<data.length;i++){if(data[i]!==null){if(data[i]==="restart"){body.attrs({to:this._conn.domain,"xml:lang":"en","xmpp:restart":"true","xmlns:xmpp":Strophe.NS.BOSH})}else{body.cnode(data[i]).up()}}}delete this._conn._data;this._conn._data=[];this._requests.push(new Strophe.Request(body.tree(),this._onRequestStateChange.bind(this,this._conn._dataRecv.bind(this._conn)),body.tree().getAttribute("rid")));this._processRequest(this._requests.length-1)}if(this._requests.length>0){var time_elapsed=this._requests[0].age();if(this._requests[0].dead!==null){if(this._requests[0].timeDead()>Math.floor(Strophe.SECONDARY_TIMEOUT*this.wait)){this._throttledRequestHandler()}}if(time_elapsed>Math.floor(Strophe.TIMEOUT*this.wait)){Strophe.warn("Request "+this._requests[0].id+" timed out, over "+Math.floor(Strophe.TIMEOUT*this.wait)+" seconds since last activity");this._throttledRequestHandler()}}},_onRequestStateChange:function(func,req){Strophe.debug("request id "+req.id+"."+req.sends+" state changed to "+req.xhr.readyState);if(req.abort){req.abort=false;return}var reqStatus;if(req.xhr.readyState==4){reqStatus=0;try{reqStatus=req.xhr.status}catch(e){}if(typeof(reqStatus)=="undefined"){reqStatus=0}if(this.disconnecting){if(reqStatus>=400){this._hitError(reqStatus);return}}var reqIs0=(this._requests[0]==req);var reqIs1=(this._requests[1]==req);if((reqStatus>0&&reqStatus<500)||req.sends>5){this._removeRequest(req);Strophe.debug("request id "+req.id+" should now be removed")}if(reqStatus==200){if(reqIs1||(reqIs0&&this._requests.length>0&&this._requests[0].age()>Math.floor(Strophe.SECONDARY_TIMEOUT*this.wait))){this._restartRequest(0)}Strophe.debug("request id "+req.id+"."+req.sends+" got 200");func(req);this.errors=0}else{Strophe.error("request id "+req.id+"."+req.sends+" error "+reqStatus+" happened");if(reqStatus===0||(reqStatus>=400&&reqStatus<600)||reqStatus>=12000){this._hitError(reqStatus);if(reqStatus>=400&&reqStatus<500){this._conn._changeConnectStatus(Strophe.Status.DISCONNECTING,null);this._conn._doDisconnect()}}}if(!((reqStatus>0&&reqStatus<500)||req.sends>5)){this._throttledRequestHandler()}}},_processRequest:function(i){var self=this;var req=this._requests[i];var reqStatus=-1;try{if(req.xhr.readyState==4){reqStatus=req.xhr.status}}catch(e){Strophe.error("caught an error in _requests["+i+"], reqStatus: "+reqStatus)}if(typeof(reqStatus)=="undefined"){reqStatus=-1}if(req.sends>this.maxRetries){this._onDisconnectTimeout();return}var time_elapsed=req.age();var primaryTimeout=(!isNaN(time_elapsed)&&time_elapsed>Math.floor(Strophe.TIMEOUT*this.wait));var secondaryTimeout=(req.dead!==null&&req.timeDead()>Math.floor(Strophe.SECONDARY_TIMEOUT*this.wait));var requestCompletedWithServerError=(req.xhr.readyState==4&&(reqStatus<1||reqStatus>=500));if(primaryTimeout||secondaryTimeout||requestCompletedWithServerError){if(secondaryTimeout){Strophe.error("Request "+this._requests[i].id+" timed out (secondary), restarting")}req.abort=true;req.xhr.abort();req.xhr.onreadystatechange=function(){};this._requests[i]=new Strophe.Request(req.xmlData,req.origFunc,req.rid,req.sends);req=this._requests[i]}if(req.xhr.readyState===0){Strophe.debug("request id "+req.id+"."+req.sends+" posting");try{req.xhr.open("POST",this._conn.service,this._conn.options.sync?false:true)}catch(e2){Strophe.error("XHR open failed.");if(!this._conn.connected){this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"bad-service")}this._conn.disconnect();return}var sendFunc=function(){req.date=new Date();if(self._conn.options.customHeaders){var headers=self._conn.options.customHeaders;for(var header in headers){if(headers.hasOwnProperty(header)){req.xhr.setRequestHeader(header,headers[header])}}}req.xhr.send(req.data)};if(req.sends>1){var backoff=Math.min(Math.floor(Strophe.TIMEOUT*this.wait),Math.pow(req.sends,3))*1000;setTimeout(sendFunc,backoff)}else{sendFunc()}req.sends++;if(this._conn.xmlOutput!==Strophe.Connection.prototype.xmlOutput){if(req.xmlData.nodeName===this.strip&&req.xmlData.childNodes.length){this._conn.xmlOutput(req.xmlData.childNodes[0])}else{this._conn.xmlOutput(req.xmlData)}}if(this._conn.rawOutput!==Strophe.Connection.prototype.rawOutput){this._conn.rawOutput(req.data)}}else{Strophe.debug("_processRequest: "+(i===0?"first":"second")+" request has readyState of "+req.xhr.readyState)}},_removeRequest:function(req){Strophe.debug("removing request");var i;for(i=this._requests.length-1;i>=0;i--){if(req==this._requests[i]){this._requests.splice(i,1)}}req.xhr.onreadystatechange=function(){};this._throttledRequestHandler()},_restartRequest:function(i){var req=this._requests[i];if(req.dead===null){req.dead=new Date()}this._processRequest(i)},_reqToData:function(req){try{return req.getResponse()}catch(e){if(e!="parsererror"){throw e}this._conn.disconnect("strophe-parsererror")}},_sendTerminate:function(pres){Strophe.info("_sendTerminate was called");var body=this._buildBody().attrs({type:"terminate"});if(pres){body.cnode(pres.tree())}var req=new Strophe.Request(body.tree(),this._onRequestStateChange.bind(this,this._conn._dataRecv.bind(this._conn)),body.tree().getAttribute("rid"));this._requests.push(req);this._throttledRequestHandler()},_send:function(){clearTimeout(this._conn._idleTimeout);this._throttledRequestHandler();this._conn._idleTimeout=setTimeout(this._conn._onIdle.bind(this._conn),100)},_sendRestart:function(){this._throttledRequestHandler();clearTimeout(this._conn._idleTimeout)},_throttledRequestHandler:function(){if(!this._requests){Strophe.debug("_throttledRequestHandler called with undefined requests")}else{Strophe.debug("_throttledRequestHandler called with "+this._requests.length+" requests")}if(!this._requests||this._requests.length===0){return}if(this._requests.length>0){this._processRequest(0)}if(this._requests.length>1&&Math.abs(this._requests[0].rid-this._requests[1].rid)<this.window){this._processRequest(1)}}};Strophe.Websocket=function(connection){this._conn=connection;this.strip="stream:stream";var service=connection.service;if(service.indexOf("ws:")!==0&&service.indexOf("wss:")!==0){var new_service="";if(connection.options.protocol==="ws"&&window.location.protocol!=="https:"){new_service+="ws"}else{new_service+="wss"}new_service+="://"+window.location.host;if(service.indexOf("/")!==0){new_service+=window.location.pathname+service}else{new_service+=service}connection.service=new_service}};Strophe.Websocket.prototype={_buildStream:function(){return $build("stream:stream",{to:this._conn.domain,xmlns:Strophe.NS.CLIENT,"xmlns:stream":Strophe.NS.STREAM,version:"1.0"})},_check_streamerror:function(bodyWrap,connectstatus){var errors=bodyWrap.getElementsByTagName("stream:error");if(errors.length===0){return false}var error=errors[0];var condition="";var text="";var ns="urn:ietf:params:xml:ns:xmpp-streams";for(var i=0;i<error.childNodes.length;i++){var e=error.childNodes[i];if(e.getAttribute("xmlns")!==ns){break}if(e.nodeName==="text"){text=e.textContent}else{condition=e.nodeName}}var errorString="WebSocket stream error: ";if(condition){errorString+=condition}else{errorString+="unknown"}if(text){errorString+=" - "+condition}Strophe.error(errorString);this._conn._changeConnectStatus(connectstatus,condition);this._conn._doDisconnect();return true},_reset:function(){return},_connect:function(){this._closeSocket();this.socket=new WebSocket(this._conn.service,"xmpp");this.socket.onopen=this._onOpen.bind(this);this.socket.onerror=this._onError.bind(this);this.socket.onclose=this._onClose.bind(this);this.socket.onmessage=this._connect_cb_wrapper.bind(this)},_connect_cb:function(bodyWrap){var error=this._check_streamerror(bodyWrap,Strophe.Status.CONNFAIL);if(error){return Strophe.Status.CONNFAIL}},_handleStreamStart:function(message){var error=false;var ns=message.getAttribute("xmlns");if(typeof ns!=="string"){error="Missing xmlns in stream:stream"}else{if(ns!==Strophe.NS.CLIENT){error="Wrong xmlns in stream:stream: "+ns}}var ns_stream=message.namespaceURI;if(typeof ns_stream!=="string"){error="Missing xmlns:stream in stream:stream"}else{if(ns_stream!==Strophe.NS.STREAM){error="Wrong xmlns:stream in stream:stream: "+ns_stream}}var ver=message.getAttribute("version");if(typeof ver!=="string"){error="Missing version in stream:stream"}else{if(ver!=="1.0"){error="Wrong version in stream:stream: "+ver}}if(error){this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,error);this._conn._doDisconnect();return false}return true},_connect_cb_wrapper:function(message){if(message.data.indexOf("<stream:stream ")===0||message.data.indexOf("<?xml")===0){var data=message.data.replace(/^(<\?.*?\?>\s*)*/,"");if(data===""){return}data=message.data.replace(/<stream:stream (.*[^\/])>/,"<stream:stream $1/>");var streamStart=new DOMParser().parseFromString(data,"text/xml").documentElement;this._conn.xmlInput(streamStart);this._conn.rawInput(message.data);if(this._handleStreamStart(streamStart)){this._connect_cb(streamStart);this.streamStart=message.data.replace(/^<stream:(.*)\/>$/,"<stream:$1>")}}else{if(message.data==="</stream:stream>"){this._conn.rawInput(message.data);this._conn.xmlInput(document.createElement("stream:stream"));this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"Received closing stream");this._conn._doDisconnect();return}else{var string=this._streamWrap(message.data);var elem=new DOMParser().parseFromString(string,"text/xml").documentElement;this.socket.onmessage=this._onMessage.bind(this);this._conn._connect_cb(elem,null,message.data)}}},_disconnect:function(pres){if(this.socket.readyState!==WebSocket.CLOSED){if(pres){this._conn.send(pres)}var close="</stream:stream>";this._conn.xmlOutput(document.createElement("stream:stream"));this._conn.rawOutput(close);try{this.socket.send(close)}catch(e){Strophe.info("Couldn't send closing stream tag.")}}this._conn._doDisconnect()},_doDisconnect:function(){Strophe.info("WebSockets _doDisconnect was called");this._closeSocket()},_streamWrap:function(stanza){return this.streamStart+stanza+"</stream:stream>"},_closeSocket:function(){if(this.socket){try{this.socket.close()}catch(e){}}this.socket=null},_emptyQueue:function(){return true},_onClose:function(){if(this._conn.connected&&!this._conn.disconnecting){Strophe.error("Websocket closed unexcectedly");this._conn._doDisconnect()}else{Strophe.info("Websocket closed")}},_no_auth_received:function(_callback){Strophe.error("Server did not send any auth methods");this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"Server did not send any auth methods");if(_callback){_callback=_callback.bind(this._conn);_callback()}this._conn._doDisconnect()},_onDisconnectTimeout:function(){},_onError:function(error){Strophe.error("Websocket error "+error);this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"The WebSocket connection could not be established was disconnected.");this._disconnect()},_onIdle:function(){var data=this._conn._data;if(data.length>0&&!this._conn.paused){for(var i=0;i<data.length;i++){if(data[i]!==null){var stanza,rawStanza;if(data[i]==="restart"){stanza=this._buildStream();rawStanza=this._removeClosingTag(stanza);stanza=stanza.tree()}else{stanza=data[i];rawStanza=Strophe.serialize(stanza)}this._conn.xmlOutput(stanza);this._conn.rawOutput(rawStanza);this.socket.send(rawStanza)}}this._conn._data=[]}},_onMessage:function(message){var elem,data;if(message.data==="</stream:stream>"){var close="</stream:stream>";this._conn.rawInput(close);this._conn.xmlInput(document.createElement("stream:stream"));if(!this._conn.disconnecting){this._conn._doDisconnect()}return}else{if(message.data.search("<stream:stream ")===0){data=message.data.replace(/<stream:stream (.*[^\/])>/,"<stream:stream $1/>");elem=new DOMParser().parseFromString(data,"text/xml").documentElement;if(!this._handleStreamStart(elem)){return}}else{data=this._streamWrap(message.data);elem=new DOMParser().parseFromString(data,"text/xml").documentElement}}if(this._check_streamerror(elem,Strophe.Status.ERROR)){return}if(this._conn.disconnecting&&elem.firstChild.nodeName==="presence"&&elem.firstChild.getAttribute("type")==="unavailable"){this._conn.xmlInput(elem);this._conn.rawInput(Strophe.serialize(elem));return}this._conn._dataRecv(elem,message.data)},_onOpen:function(){Strophe.info("Websocket open");var start=this._buildStream();this._conn.xmlOutput(start.tree());var startString=this._removeClosingTag(start);this._conn.rawOutput(startString);this.socket.send(startString)},_removeClosingTag:function(elem){var string=Strophe.serialize(elem);string=string.replace(/<(stream:stream .*[^\/])\/>$/,"<$1>");return string},_reqToData:function(stanza){return stanza},_send:function(){this._conn.flush()},_sendRestart:function(){clearTimeout(this._conn._idleTimeout);this._conn._onIdle.bind(this._conn)()}};
\ No newline at end of file
diff --git a/panikweb/static/js/strophe.muc.js b/panikweb/static/js/strophe.muc.js
new file mode 100644 (file)
index 0000000..a96f61c
--- /dev/null
@@ -0,0 +1,1144 @@
+/*
+ *Plugin to implement the MUC extension.
+ http://xmpp.org/extensions/xep-0045.html
+ *Previous Author:
+ Nathan Zorn <nathan.zorn@gmail.com>
+ *Complete CoffeeScript rewrite:
+ Andreas Guth <guth@dbis.rwth-aachen.de>
+ */
+var Occupant, RoomConfig, XmppRoom,
+    hasProp = {}.hasOwnProperty,
+    bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+
+Strophe.addConnectionPlugin('muc', {
+  _connection: null,
+  rooms: {},
+  roomNames: [],
+
+  /*Function
+   Initialize the MUC plugin. Sets the correct connection object and
+   extends the namesace.
+   */
+  init: function(conn) {
+    this._connection = conn;
+    this._muc_handler = null;
+    Strophe.addNamespace('MUC_OWNER', Strophe.NS.MUC + "#owner");
+    Strophe.addNamespace('MUC_ADMIN', Strophe.NS.MUC + "#admin");
+    Strophe.addNamespace('MUC_USER', Strophe.NS.MUC + "#user");
+    Strophe.addNamespace('MUC_ROOMCONF', Strophe.NS.MUC + "#roomconfig");
+    return Strophe.addNamespace('MUC_REGISTER', "jabber:iq:register");
+  },
+
+  /*Function
+   Join a multi-user chat room
+   Parameters:
+   (String) room - The multi-user chat room to join.
+   (String) nick - The nickname to use in the chat room. Optional
+   (Function) msg_handler_cb - The function call to handle messages from the
+   specified chat room.
+   (Function) pres_handler_cb - The function call back to handle presence
+   in the chat room.
+   (Function) roster_cb - The function call to handle roster info in the chat room
+   (String) password - The optional password to use. (password protected
+   rooms only)
+   (Object) history_attrs - Optional attributes for retrieving history
+   (XML DOM Element) extended_presence - Optional XML for extending presence
+   */
+  join: function(room, nick, msg_handler_cb, pres_handler_cb, roster_cb, password, history_attrs, extended_presence) {
+    var msg, room_nick;
+    room_nick = this.test_append_nick(room, nick);
+    msg = $pres({
+      from: this._connection.jid,
+      to: room_nick
+    }).c("x", {
+      xmlns: Strophe.NS.MUC
+    });
+    if (history_attrs != null) {
+      msg = msg.c("history", history_attrs).up();
+    }
+    if (password != null) {
+      msg.cnode(Strophe.xmlElement("password", [], password));
+    }
+    if (extended_presence != null) {
+      msg.up().cnode(extended_presence);
+    }
+    if (this._muc_handler == null) {
+      this._muc_handler = this._connection.addHandler((function(_this) {
+        return function(stanza) {
+          var from, handler, handlers, i, id, len, roomname, x, xmlns, xquery;
+          from = stanza.getAttribute('from');
+          if (!from) {
+            return true;
+          }
+          roomname = from.split("/")[0];
+          if (!_this.rooms[roomname]) {
+            return true;
+          }
+          room = _this.rooms[roomname];
+          handlers = {};
+          if (stanza.nodeName === "message") {
+            handlers = room._message_handlers;
+          } else if (stanza.nodeName === "presence") {
+            xquery = stanza.getElementsByTagName("x");
+            if (xquery.length > 0) {
+              for (i = 0, len = xquery.length; i < len; i++) {
+                x = xquery[i];
+                xmlns = x.getAttribute("xmlns");
+                if (xmlns && xmlns.match(Strophe.NS.MUC)) {
+                  handlers = room._presence_handlers;
+                  break;
+                }
+              }
+            }
+          }
+          for (id in handlers) {
+            handler = handlers[id];
+            if (!handler(stanza, room)) {
+              delete handlers[id];
+            }
+          }
+          return true;
+        };
+      })(this));
+    }
+    if (!this.rooms.hasOwnProperty(room)) {
+      this.rooms[room] = new XmppRoom(this, room, nick, password);
+      if (pres_handler_cb) {
+        this.rooms[room].addHandler('presence', pres_handler_cb);
+      }
+      if (msg_handler_cb) {
+        this.rooms[room].addHandler('message', msg_handler_cb);
+      }
+      if (roster_cb) {
+        this.rooms[room].addHandler('roster', roster_cb);
+      }
+      this.roomNames.push(room);
+    }
+    return this._connection.send(msg);
+  },
+
+  /*Function
+   Leave a multi-user chat room
+   Parameters:
+   (String) room - The multi-user chat room to leave.
+   (String) nick - The nick name used in the room.
+   (Function) handler_cb - Optional function to handle the successful leave.
+   (String) exit_msg - optional exit message.
+   Returns:
+   iqid - The unique id for the room leave.
+   */
+  leave: function(room, nick, handler_cb, exit_msg) {
+    var id, presence, presenceid, room_nick;
+    id = this.roomNames.indexOf(room);
+    delete this.rooms[room];
+    if (id >= 0) {
+      this.roomNames.splice(id, 1);
+      if (this.roomNames.length === 0) {
+        this._connection.deleteHandler(this._muc_handler);
+        this._muc_handler = null;
+      }
+    }
+    room_nick = this.test_append_nick(room, nick);
+    presenceid = this._connection.getUniqueId();
+    presence = $pres({
+      type: "unavailable",
+      id: presenceid,
+      from: this._connection.jid,
+      to: room_nick
+    });
+    if (exit_msg != null) {
+      presence.c("status", exit_msg);
+    }
+    if (handler_cb != null) {
+      this._connection.addHandler(handler_cb, null, "presence", null, presenceid);
+    }
+    this._connection.send(presence);
+    return presenceid;
+  },
+
+  /*Function
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (String) nick - The nick name used in the chat room.
+   (String) message - The plaintext message to send to the room.
+   (String) html_message - The message to send to the room with html markup.
+   (String) type - "groupchat" for group chat messages o
+   "chat" for private chat messages
+   Returns:
+   msgiq - the unique id used to send the message
+   */
+  message: function(room, nick, message, html_message, type, msgid) {
+    var msg, parent, room_nick;
+    room_nick = this.test_append_nick(room, nick);
+    type = type || (nick != null ? "chat" : "groupchat");
+    msgid = msgid || this._connection.getUniqueId();
+    msg = $msg({
+      to: room_nick,
+      from: this._connection.jid,
+      type: type,
+      id: msgid
+    }).c("body").t(message);
+    msg.up();
+    if (html_message != null) {
+      msg.c("html", {
+        xmlns: Strophe.NS.XHTML_IM
+      }).c("body", {
+        xmlns: Strophe.NS.XHTML
+      }).h(html_message);
+      if (msg.node.childNodes.length === 0) {
+        parent = msg.node.parentNode;
+        msg.up().up();
+        msg.node.removeChild(parent);
+      } else {
+        msg.up().up();
+      }
+    }
+    msg.c("x", {
+      xmlns: "jabber:x:event"
+    }).c("composing");
+    this._connection.send(msg);
+    return msgid;
+  },
+
+  /*Function
+   Convenience Function to send a Message to all Occupants
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (String) message - The plaintext message to send to the room.
+   (String) html_message - The message to send to the room with html markup.
+   (String) msgid - Optional unique ID which will be set as the 'id' attribute of the stanza
+   Returns:
+   msgiq - the unique id used to send the message
+   */
+  groupchat: function(room, message, html_message, msgid) {
+    return this.message(room, null, message, html_message, void 0, msgid);
+  },
+
+  /*Function
+   Send a mediated invitation.
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (String) receiver - The invitation's receiver.
+   (String) reason - Optional reason for joining the room.
+   Returns:
+   msgiq - the unique id used to send the invitation
+   */
+  invite: function(room, receiver, reason) {
+    var invitation, msgid;
+    msgid = this._connection.getUniqueId();
+    invitation = $msg({
+      from: this._connection.jid,
+      to: room,
+      id: msgid
+    }).c('x', {
+      xmlns: Strophe.NS.MUC_USER
+    }).c('invite', {
+      to: receiver
+    });
+    if (reason != null) {
+      invitation.c('reason', reason);
+    }
+    this._connection.send(invitation);
+    return msgid;
+  },
+
+  /*Function
+   Send a mediated multiple invitation.
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (Array) receivers - The invitation's receivers.
+   (String) reason - Optional reason for joining the room.
+   Returns:
+   msgiq - the unique id used to send the invitation
+   */
+  multipleInvites: function(room, receivers, reason) {
+    var i, invitation, len, msgid, receiver;
+    msgid = this._connection.getUniqueId();
+    invitation = $msg({
+      from: this._connection.jid,
+      to: room,
+      id: msgid
+    }).c('x', {
+      xmlns: Strophe.NS.MUC_USER
+    });
+    for (i = 0, len = receivers.length; i < len; i++) {
+      receiver = receivers[i];
+      invitation.c('invite', {
+        to: receiver
+      });
+      if (reason != null) {
+        invitation.c('reason', reason);
+        invitation.up();
+      }
+      invitation.up();
+    }
+    this._connection.send(invitation);
+    return msgid;
+  },
+
+  /*Function
+   Send a direct invitation.
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (String) receiver - The invitation's receiver.
+   (String) reason - Optional reason for joining the room.
+   (String) password - Optional password for the room.
+   Returns:
+   msgiq - the unique id used to send the invitation
+   */
+  directInvite: function(room, receiver, reason, password) {
+    var attrs, invitation, msgid;
+    msgid = this._connection.getUniqueId();
+    attrs = {
+      xmlns: 'jabber:x:conference',
+      jid: room
+    };
+    if (reason != null) {
+      attrs.reason = reason;
+    }
+    if (password != null) {
+      attrs.password = password;
+    }
+    invitation = $msg({
+      from: this._connection.jid,
+      to: receiver,
+      id: msgid
+    }).c('x', attrs);
+    this._connection.send(invitation);
+    return msgid;
+  },
+
+  /*Function
+   Queries a room for a list of occupants
+   (String) room - The multi-user chat room name.
+   (Function) success_cb - Optional function to handle the info.
+   (Function) error_cb - Optional function to handle an error.
+   Returns:
+   id - the unique id used to send the info request
+   */
+  queryOccupants: function(room, success_cb, error_cb) {
+    var attrs, info;
+    attrs = {
+      xmlns: Strophe.NS.DISCO_ITEMS
+    };
+    info = $iq({
+      from: this._connection.jid,
+      to: room,
+      type: 'get'
+    }).c('query', attrs);
+    return this._connection.sendIQ(info, success_cb, error_cb);
+  },
+
+  /*Function
+   Start a room configuration.
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (Function) handler_cb - Optional function to handle the config form.
+   Returns:
+   id - the unique id used to send the configuration request
+   */
+  configure: function(room, handler_cb, error_cb) {
+    var config, stanza;
+    config = $iq({
+      to: room,
+      type: "get"
+    }).c("query", {
+      xmlns: Strophe.NS.MUC_OWNER
+    });
+    stanza = config.tree();
+    return this._connection.sendIQ(stanza, handler_cb, error_cb);
+  },
+
+  /*Function
+   Cancel the room configuration
+   Parameters:
+   (String) room - The multi-user chat room name.
+   Returns:
+   id - the unique id used to cancel the configuration.
+   */
+  cancelConfigure: function(room) {
+    var config, stanza;
+    config = $iq({
+      to: room,
+      type: "set"
+    }).c("query", {
+      xmlns: Strophe.NS.MUC_OWNER
+    }).c("x", {
+      xmlns: "jabber:x:data",
+      type: "cancel"
+    });
+    stanza = config.tree();
+    return this._connection.sendIQ(stanza);
+  },
+
+  /*Function
+   Save a room configuration.
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (Array) config- Form Object or an array of form elements used to configure the room.
+   Returns:
+   id - the unique id used to save the configuration.
+   */
+  saveConfiguration: function(room, config, success_cb, error_cb) {
+    var conf, i, iq, len, stanza;
+    iq = $iq({
+      to: room,
+      type: "set"
+    }).c("query", {
+      xmlns: Strophe.NS.MUC_OWNER
+    });
+    if (typeof Strophe.x !== "undefined" && typeof Strophe.x.Form !== "undefined" && config instanceof Strophe.x.Form) {
+      config.type = "submit";
+      iq.cnode(config.toXML());
+    } else {
+      iq.c("x", {
+        xmlns: "jabber:x:data",
+        type: "submit"
+      });
+      for (i = 0, len = config.length; i < len; i++) {
+        conf = config[i];
+        iq.cnode(conf).up();
+      }
+    }
+    stanza = iq.tree();
+    return this._connection.sendIQ(stanza, success_cb, error_cb);
+  },
+
+  /*Function
+   Parameters:
+   (String) room - The multi-user chat room name.
+   Returns:
+   id - the unique id used to create the chat room.
+   */
+  createInstantRoom: function(room, success_cb, error_cb) {
+    var roomiq;
+    roomiq = $iq({
+      to: room,
+      type: "set"
+    }).c("query", {
+      xmlns: Strophe.NS.MUC_OWNER
+    }).c("x", {
+      xmlns: "jabber:x:data",
+      type: "submit"
+    });
+    return this._connection.sendIQ(roomiq.tree(), success_cb, error_cb);
+  },
+
+  /*Function
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (Object) config - the configuration. ex: {"muc#roomconfig_publicroom": "0", "muc#roomconfig_persistentroom": "1"}
+   Returns:
+   id - the unique id used to create the chat room.
+   */
+  createConfiguredRoom: function(room, config, success_cb, error_cb) {
+    var k, roomiq, v;
+    roomiq = $iq({
+      to: room,
+      type: "set"
+    }).c("query", {
+      xmlns: Strophe.NS.MUC_OWNER
+    }).c("x", {
+      xmlns: "jabber:x:data",
+      type: "submit"
+    });
+    roomiq.c('field', {
+      'var': 'FORM_TYPE'
+    }).c('value').t('http://jabber.org/protocol/muc#roomconfig').up().up();
+    for (k in config) {
+      if (!hasProp.call(config, k)) continue;
+      v = config[k];
+      roomiq.c('field', {
+        'var': k
+      }).c('value').t(v).up().up();
+    }
+    return this._connection.sendIQ(roomiq.tree(), success_cb, error_cb);
+  },
+
+  /*Function
+   Set the topic of the chat room.
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (String) topic - Topic message.
+   */
+  setTopic: function(room, topic) {
+    var msg;
+    msg = $msg({
+      to: room,
+      from: this._connection.jid,
+      type: "groupchat"
+    }).c("subject", {
+      xmlns: "jabber:client"
+    }).t(topic);
+    return this._connection.send(msg.tree());
+  },
+
+  /*Function
+   Internal Function that Changes the role or affiliation of a member
+   of a MUC room. This function is used by modifyRole and modifyAffiliation.
+   The modification can only be done by a room moderator. An error will be
+   returned if the user doesn't have permission.
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (Object) item - Object with nick and role or jid and affiliation attribute
+   (String) reason - Optional reason for the change.
+   (Function) handler_cb - Optional callback for success
+   (Function) error_cb - Optional callback for error
+   Returns:
+   iq - the id of the mode change request.
+   */
+  _modifyPrivilege: function(room, item, reason, handler_cb, error_cb) {
+    var iq;
+    iq = $iq({
+      to: room,
+      type: "set"
+    }).c("query", {
+      xmlns: Strophe.NS.MUC_ADMIN
+    }).cnode(item.node);
+    if (reason != null) {
+      iq.c("reason", reason);
+    }
+    return this._connection.sendIQ(iq.tree(), handler_cb, error_cb);
+  },
+
+  /*Function
+   Changes the role of a member of a MUC room.
+   The modification can only be done by a room moderator. An error will be
+   returned if the user doesn't have permission.
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (String) nick - The nick name of the user to modify.
+   (String) role - The new role of the user.
+   (String) affiliation - The new affiliation of the user.
+   (String) reason - Optional reason for the change.
+   (Function) handler_cb - Optional callback for success
+   (Function) error_cb - Optional callback for error
+   Returns:
+   iq - the id of the mode change request.
+   */
+  modifyRole: function(room, nick, role, reason, handler_cb, error_cb) {
+    var item;
+    item = $build("item", {
+      nick: nick,
+      role: role
+    });
+    return this._modifyPrivilege(room, item, reason, handler_cb, error_cb);
+  },
+  kick: function(room, nick, reason, handler_cb, error_cb) {
+    return this.modifyRole(room, nick, 'none', reason, handler_cb, error_cb);
+  },
+  voice: function(room, nick, reason, handler_cb, error_cb) {
+    return this.modifyRole(room, nick, 'participant', reason, handler_cb, error_cb);
+  },
+  mute: function(room, nick, reason, handler_cb, error_cb) {
+    return this.modifyRole(room, nick, 'visitor', reason, handler_cb, error_cb);
+  },
+  op: function(room, nick, reason, handler_cb, error_cb) {
+    return this.modifyRole(room, nick, 'moderator', reason, handler_cb, error_cb);
+  },
+  deop: function(room, nick, reason, handler_cb, error_cb) {
+    return this.modifyRole(room, nick, 'participant', reason, handler_cb, error_cb);
+  },
+
+  /*Function
+   Changes the affiliation of a member of a MUC room.
+   The modification can only be done by a room moderator. An error will be
+   returned if the user doesn't have permission.
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (String) jid  - The jid of the user to modify.
+   (String) affiliation - The new affiliation of the user.
+   (String) reason - Optional reason for the change.
+   (Function) handler_cb - Optional callback for success
+   (Function) error_cb - Optional callback for error
+   Returns:
+   iq - the id of the mode change request.
+   */
+  modifyAffiliation: function(room, jid, affiliation, reason, handler_cb, error_cb) {
+    var item;
+    item = $build("item", {
+      jid: jid,
+      affiliation: affiliation
+    });
+    return this._modifyPrivilege(room, item, reason, handler_cb, error_cb);
+  },
+  ban: function(room, jid, reason, handler_cb, error_cb) {
+    return this.modifyAffiliation(room, jid, 'outcast', reason, handler_cb, error_cb);
+  },
+  member: function(room, jid, reason, handler_cb, error_cb) {
+    return this.modifyAffiliation(room, jid, 'member', reason, handler_cb, error_cb);
+  },
+  revoke: function(room, jid, reason, handler_cb, error_cb) {
+    return this.modifyAffiliation(room, jid, 'none', reason, handler_cb, error_cb);
+  },
+  owner: function(room, jid, reason, handler_cb, error_cb) {
+    return this.modifyAffiliation(room, jid, 'owner', reason, handler_cb, error_cb);
+  },
+  admin: function(room, jid, reason, handler_cb, error_cb) {
+    return this.modifyAffiliation(room, jid, 'admin', reason, handler_cb, error_cb);
+  },
+
+  /*Function
+   Change the current users nick name.
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (String) user - The new nick name.
+   */
+  changeNick: function(room, user) {
+    var presence, room_nick;
+    room_nick = this.test_append_nick(room, user);
+    presence = $pres({
+      from: this._connection.jid,
+      to: room_nick,
+      id: this._connection.getUniqueId()
+    });
+    return this._connection.send(presence.tree());
+  },
+
+  /*Function
+   Change the current users status.
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (String) user - The current nick.
+   (String) show - The new show-text.
+   (String) status - The new status-text.
+   */
+  setStatus: function(room, user, show, status) {
+    var presence, room_nick;
+    room_nick = this.test_append_nick(room, user);
+    presence = $pres({
+      from: this._connection.jid,
+      to: room_nick
+    });
+    if (show != null) {
+      presence.c('show', show).up();
+    }
+    if (status != null) {
+      presence.c('status', status);
+    }
+    return this._connection.send(presence.tree());
+  },
+
+  /*Function
+   Registering with a room.
+   @see http://xmpp.org/extensions/xep-0045.html#register
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (Function) handle_cb - Function to call for room list return.
+   (Function) error_cb - Function to call on error.
+   */
+  registrationRequest: function(room, handle_cb, error_cb) {
+    var iq;
+    iq = $iq({
+      to: room,
+      from: this._connection.jid,
+      type: "get"
+    }).c("query", {
+      xmlns: Strophe.NS.MUC_REGISTER
+    });
+    return this._connection.sendIQ(iq, function(stanza) {
+      var $field, $fields, field, fields, i, len, length;
+      $fields = stanza.getElementsByTagName('field');
+      length = $fields.length;
+      fields = {
+        required: [],
+        optional: []
+      };
+      for (i = 0, len = $fields.length; i < len; i++) {
+        $field = $fields[i];
+        field = {
+          "var": $field.getAttribute('var'),
+          label: $field.getAttribute('label'),
+          type: $field.getAttribute('type')
+        };
+        if ($field.getElementsByTagName('required').length > 0) {
+          fields.required.push(field);
+        } else {
+          fields.optional.push(field);
+        }
+      }
+      return handle_cb(fields);
+    }, error_cb);
+  },
+
+  /*Function
+   Submits registration form.
+   Parameters:
+   (String) room - The multi-user chat room name.
+   (Function) handle_cb - Function to call for room list return.
+   (Function) error_cb - Function to call on error.
+   */
+  submitRegistrationForm: function(room, fields, handle_cb, error_cb) {
+    var iq, key, val;
+    iq = $iq({
+      to: room,
+      type: "set"
+    }).c("query", {
+      xmlns: Strophe.NS.MUC_REGISTER
+    });
+    iq.c("x", {
+      xmlns: "jabber:x:data",
+      type: "submit"
+    });
+    iq.c('field', {
+      'var': 'FORM_TYPE'
+    }).c('value').t('http://jabber.org/protocol/muc#register').up().up();
+    for (key in fields) {
+      val = fields[key];
+      iq.c('field', {
+        'var': key
+      }).c('value').t(val).up().up();
+    }
+    return this._connection.sendIQ(iq, handle_cb, error_cb);
+  },
+
+  /*Function
+   List all chat room available on a server.
+   Parameters:
+   (String) server - name of chat server.
+   (String) handle_cb - Function to call for room list return.
+   (String) error_cb - Function to call on error.
+   */
+  listRooms: function(server, handle_cb, error_cb) {
+    var iq;
+    iq = $iq({
+      to: server,
+      from: this._connection.jid,
+      type: "get"
+    }).c("query", {
+      xmlns: Strophe.NS.DISCO_ITEMS
+    });
+    return this._connection.sendIQ(iq, handle_cb, error_cb);
+  },
+  test_append_nick: function(room, nick) {
+    var domain, node;
+    node = Strophe.escapeNode(Strophe.getNodeFromJid(room));
+    domain = Strophe.getDomainFromJid(room);
+    return node + "@" + domain + (nick != null ? "/" + nick : "");
+  }
+});
+
+XmppRoom = (function() {
+  function XmppRoom(client, name1, nick1, password1) {
+    this.client = client;
+    this.name = name1;
+    this.nick = nick1;
+    this.password = password1;
+    this._roomRosterHandler = bind(this._roomRosterHandler, this);
+    this._addOccupant = bind(this._addOccupant, this);
+    this.roster = {};
+    this._message_handlers = {};
+    this._presence_handlers = {};
+    this._roster_handlers = {};
+    this._handler_ids = 0;
+    if (this.client.muc) {
+      this.client = this.client.muc;
+    }
+    this.name = Strophe.getBareJidFromJid(this.name);
+    this.addHandler('presence', this._roomRosterHandler);
+  }
+
+  XmppRoom.prototype.join = function(msg_handler_cb, pres_handler_cb, roster_cb) {
+    return this.client.join(this.name, this.nick, msg_handler_cb, pres_handler_cb, roster_cb, this.password);
+  };
+
+  XmppRoom.prototype.leave = function(handler_cb, message) {
+    this.client.leave(this.name, this.nick, handler_cb, message);
+    return delete this.client.rooms[this.name];
+  };
+
+  XmppRoom.prototype.message = function(nick, message, html_message, type) {
+    return this.client.message(this.name, nick, message, html_message, type);
+  };
+
+  XmppRoom.prototype.groupchat = function(message, html_message) {
+    return this.client.groupchat(this.name, message, html_message);
+  };
+
+  XmppRoom.prototype.invite = function(receiver, reason) {
+    return this.client.invite(this.name, receiver, reason);
+  };
+
+  XmppRoom.prototype.multipleInvites = function(receivers, reason) {
+    return this.client.invite(this.name, receivers, reason);
+  };
+
+  XmppRoom.prototype.directInvite = function(receiver, reason) {
+    return this.client.directInvite(this.name, receiver, reason, this.password);
+  };
+
+  XmppRoom.prototype.configure = function(handler_cb) {
+    return this.client.configure(this.name, handler_cb);
+  };
+
+  XmppRoom.prototype.cancelConfigure = function() {
+    return this.client.cancelConfigure(this.name);
+  };
+
+  XmppRoom.prototype.saveConfiguration = function(config) {
+    return this.client.saveConfiguration(this.name, config);
+  };
+
+  XmppRoom.prototype.queryOccupants = function(success_cb, error_cb) {
+    return this.client.queryOccupants(this.name, success_cb, error_cb);
+  };
+
+  XmppRoom.prototype.setTopic = function(topic) {
+    return this.client.setTopic(this.name, topic);
+  };
+
+  XmppRoom.prototype.modifyRole = function(nick, role, reason, success_cb, error_cb) {
+    return this.client.modifyRole(this.name, nick, role, reason, success_cb, error_cb);
+  };
+
+  XmppRoom.prototype.kick = function(nick, reason, handler_cb, error_cb) {
+    return this.client.kick(this.name, nick, reason, handler_cb, error_cb);
+  };
+
+  XmppRoom.prototype.voice = function(nick, reason, handler_cb, error_cb) {
+    return this.client.voice(this.name, nick, reason, handler_cb, error_cb);
+  };
+
+  XmppRoom.prototype.mute = function(nick, reason, handler_cb, error_cb) {
+    return this.client.mute(this.name, nick, reason, handler_cb, error_cb);
+  };
+
+  XmppRoom.prototype.op = function(nick, reason, handler_cb, error_cb) {
+    return this.client.op(this.name, nick, reason, handler_cb, error_cb);
+  };
+
+  XmppRoom.prototype.deop = function(nick, reason, handler_cb, error_cb) {
+    return this.client.deop(this.name, nick, reason, handler_cb, error_cb);
+  };
+
+  XmppRoom.prototype.modifyAffiliation = function(jid, affiliation, reason, success_cb, error_cb) {
+    return this.client.modifyAffiliation(this.name, jid, affiliation, reason, success_cb, error_cb);
+  };
+
+  XmppRoom.prototype.ban = function(jid, reason, handler_cb, error_cb) {
+    return this.client.ban(this.name, jid, reason, handler_cb, error_cb);
+  };
+
+  XmppRoom.prototype.member = function(jid, reason, handler_cb, error_cb) {
+    return this.client.member(this.name, jid, reason, handler_cb, error_cb);
+  };
+
+  XmppRoom.prototype.revoke = function(jid, reason, handler_cb, error_cb) {
+    return this.client.revoke(this.name, jid, reason, handler_cb, error_cb);
+  };
+
+  XmppRoom.prototype.owner = function(jid, reason, handler_cb, error_cb) {
+    return this.client.owner(this.name, jid, reason, handler_cb, error_cb);
+  };
+
+  XmppRoom.prototype.admin = function(jid, reason, handler_cb, error_cb) {
+    return this.client.admin(this.name, jid, reason, handler_cb, error_cb);
+  };
+
+  XmppRoom.prototype.changeNick = function(nick1) {
+    this.nick = nick1;
+    return this.client.changeNick(this.name, nick);
+  };
+
+  XmppRoom.prototype.setStatus = function(show, status) {
+    return this.client.setStatus(this.name, this.nick, show, status);
+  };
+
+
+  /*Function
+   Adds a handler to the MUC room.
+   Parameters:
+   (String) handler_type - 'message', 'presence' or 'roster'.
+   (Function) handler - The handler function.
+   Returns:
+   id - the id of handler.
+   */
+
+  XmppRoom.prototype.addHandler = function(handler_type, handler) {
+    var id;
+    id = this._handler_ids++;
+    switch (handler_type) {
+      case 'presence':
+        this._presence_handlers[id] = handler;
+        break;
+      case 'message':
+        this._message_handlers[id] = handler;
+        break;
+      case 'roster':
+        this._roster_handlers[id] = handler;
+        break;
+      default:
+        this._handler_ids--;
+        return null;
+    }
+    return id;
+  };
+
+
+  /*Function
+   Removes a handler from the MUC room.
+   This function takes ONLY ids returned by the addHandler function
+   of this room. passing handler ids returned by connection.addHandler
+   may brake things!
+   Parameters:
+   (number) id - the id of the handler
+   */
+
+  XmppRoom.prototype.removeHandler = function(id) {
+    delete this._presence_handlers[id];
+    delete this._message_handlers[id];
+    return delete this._roster_handlers[id];
+  };
+
+
+  /*Function
+   Creates and adds an Occupant to the Room Roster.
+   Parameters:
+   (Object) data - the data the Occupant is filled with
+   Returns:
+   occ - the created Occupant.
+   */
+
+  XmppRoom.prototype._addOccupant = function(data) {
+    var occ;
+    occ = new Occupant(data, this);
+    this.roster[occ.nick] = occ;
+    return occ;
+  };
+
+
+  /*Function
+   The standard handler that managed the Room Roster.
+   Parameters:
+   (Object) pres - the presence stanza containing user information
+   */
+
+  XmppRoom.prototype._roomRosterHandler = function(pres) {
+    var data, handler, id, newnick, nick, ref;
+    data = XmppRoom._parsePresence(pres);
+    nick = data.nick;
+    newnick = data.newnick || null;
+    switch (data.type) {
+      case 'error':
+        return true;
+      case 'unavailable':
+        if (newnick) {
+          data.nick = newnick;
+          if (this.roster[nick] && this.roster[newnick]) {
+            this.roster[nick].update(this.roster[newnick]);
+            this.roster[newnick] = this.roster[nick];
+          }
+          if (this.roster[nick] && !this.roster[newnick]) {
+            this.roster[newnick] = this.roster[nick].update(data);
+          }
+        }
+        delete this.roster[nick];
+        break;
+      default:
+        if (this.roster[nick]) {
+          this.roster[nick].update(data);
+        } else {
+          this._addOccupant(data);
+        }
+    }
+    ref = this._roster_handlers;
+    for (id in ref) {
+      handler = ref[id];
+      if (!handler(this.roster, this)) {
+        delete this._roster_handlers[id];
+      }
+    }
+    return true;
+  };
+
+
+  /*Function
+   Parses a presence stanza
+   Parameters:
+   (Object) data - the data extracted from the presence stanza
+   */
+
+  XmppRoom._parsePresence = function(pres) {
+    var c, c2, data, i, j, len, len1, ref, ref1;
+    data = {};
+    data.nick = Strophe.getResourceFromJid(pres.getAttribute("from"));
+    data.type = pres.getAttribute("type");
+    data.states = [];
+    ref = pres.childNodes;
+    for (i = 0, len = ref.length; i < len; i++) {
+      c = ref[i];
+      switch (c.nodeName) {
+        case "status":
+          data.status = c.textContent || null;
+          break;
+        case "show":
+          data.show = c.textContent || null;
+          break;
+        case "x":
+          if (c.getAttribute("xmlns") === Strophe.NS.MUC_USER) {
+            ref1 = c.childNodes;
+            for (j = 0, len1 = ref1.length; j < len1; j++) {
+              c2 = ref1[j];
+              switch (c2.nodeName) {
+                case "item":
+                  data.affiliation = c2.getAttribute("affiliation");
+                  data.role = c2.getAttribute("role");
+                  data.jid = c2.getAttribute("jid");
+                  data.newnick = c2.getAttribute("nick");
+                  break;
+                case "status":
+                  if (c2.getAttribute("code")) {
+                    data.states.push(c2.getAttribute("code"));
+                  }
+              }
+            }
+          }
+      }
+    }
+    return data;
+  };
+
+  return XmppRoom;
+
+})();
+
+RoomConfig = (function() {
+  function RoomConfig(info) {
+    this.parse = bind(this.parse, this);
+    if (info != null) {
+      this.parse(info);
+    }
+  }
+
+  RoomConfig.prototype.parse = function(result) {
+    var attr, attrs, child, field, i, identity, j, l, len, len1, len2, query, ref;
+    query = result.getElementsByTagName("query")[0].childNodes;
+    this.identities = [];
+    this.features = [];
+    this.x = [];
+    for (i = 0, len = query.length; i < len; i++) {
+      child = query[i];
+      attrs = child.attributes;
+      switch (child.nodeName) {
+        case "identity":
+          identity = {};
+          for (j = 0, len1 = attrs.length; j < len1; j++) {
+            attr = attrs[j];
+            identity[attr.name] = attr.textContent;
+          }
+          this.identities.push(identity);
+          break;
+        case "feature":
+          this.features.push(child.getAttribute("var"));
+          break;
+        case "x":
+          if ((!child.childNodes[0].getAttribute("var") === 'FORM_TYPE') || (!child.childNodes[0].getAttribute("type") === 'hidden')) {
+            break;
+          }
+          ref = child.childNodes;
+          for (l = 0, len2 = ref.length; l < len2; l++) {
+            field = ref[l];
+            if (!field.attributes.type) {
+              this.x.push({
+                "var": field.getAttribute("var"),
+                label: field.getAttribute("label") || "",
+                value: field.firstChild.textContent || ""
+              });
+            }
+          }
+      }
+    }
+    return {
+      "identities": this.identities,
+      "features": this.features,
+      "x": this.x
+    };
+  };
+
+  return RoomConfig;
+
+})();
+
+Occupant = (function() {
+  function Occupant(data, room1) {
+    this.room = room1;
+    this.update = bind(this.update, this);
+    this.admin = bind(this.admin, this);
+    this.owner = bind(this.owner, this);
+    this.revoke = bind(this.revoke, this);
+    this.member = bind(this.member, this);
+    this.ban = bind(this.ban, this);
+    this.modifyAffiliation = bind(this.modifyAffiliation, this);
+    this.deop = bind(this.deop, this);
+    this.op = bind(this.op, this);
+    this.mute = bind(this.mute, this);
+    this.voice = bind(this.voice, this);
+    this.kick = bind(this.kick, this);
+    this.modifyRole = bind(this.modifyRole, this);
+    this.update(data);
+  }
+
+  Occupant.prototype.modifyRole = function(role, reason, success_cb, error_cb) {
+    return this.room.modifyRole(this.nick, role, reason, success_cb, error_cb);
+  };
+
+  Occupant.prototype.kick = function(reason, handler_cb, error_cb) {
+    return this.room.kick(this.nick, reason, handler_cb, error_cb);
+  };
+
+  Occupant.prototype.voice = function(reason, handler_cb, error_cb) {
+    return this.room.voice(this.nick, reason, handler_cb, error_cb);
+  };
+
+  Occupant.prototype.mute = function(reason, handler_cb, error_cb) {
+    return this.room.mute(this.nick, reason, handler_cb, error_cb);
+  };
+
+  Occupant.prototype.op = function(reason, handler_cb, error_cb) {
+    return this.room.op(this.nick, reason, handler_cb, error_cb);
+  };
+
+  Occupant.prototype.deop = function(reason, handler_cb, error_cb) {
+    return this.room.deop(this.nick, reason, handler_cb, error_cb);
+  };
+
+  Occupant.prototype.modifyAffiliation = function(affiliation, reason, success_cb, error_cb) {
+    return this.room.modifyAffiliation(this.jid, affiliation, reason, success_cb, error_cb);
+  };
+
+  Occupant.prototype.ban = function(reason, handler_cb, error_cb) {
+    return this.room.ban(this.jid, reason, handler_cb, error_cb);
+  };
+
+  Occupant.prototype.member = function(reason, handler_cb, error_cb) {
+    return this.room.member(this.jid, reason, handler_cb, error_cb);
+  };
+
+  Occupant.prototype.revoke = function(reason, handler_cb, error_cb) {
+    return this.room.revoke(this.jid, reason, handler_cb, error_cb);
+  };
+
+  Occupant.prototype.owner = function(reason, handler_cb, error_cb) {
+    return this.room.owner(this.jid, reason, handler_cb, error_cb);
+  };
+
+  Occupant.prototype.admin = function(reason, handler_cb, error_cb) {
+    return this.room.admin(this.jid, reason, handler_cb, error_cb);
+  };
+
+  Occupant.prototype.update = function(data) {
+    this.nick = data.nick || null;
+    this.affiliation = data.affiliation || null;
+    this.role = data.role || null;
+    this.jid = data.jid || null;
+    this.status = data.status || null;
+    this.show = data.show || null;
+    return this;
+  };
+
+  return Occupant;
+
+})();
+
+// ---
+// generated by coffee-script 1.9.2
\ No newline at end of file
diff --git a/panikweb/static/reglo/RE01.otf b/panikweb/static/reglo/RE01.otf
new file mode 100644 (file)
index 0000000..d5bd21a
Binary files /dev/null and b/panikweb/static/reglo/RE01.otf differ
diff --git a/panikweb/static/reglo/RE02-Medium.otf b/panikweb/static/reglo/RE02-Medium.otf
new file mode 100644 (file)
index 0000000..e0cbce4
Binary files /dev/null and b/panikweb/static/reglo/RE02-Medium.otf differ
diff --git a/panikweb/static/reglo/RE03-Bold.otf b/panikweb/static/reglo/RE03-Bold.otf
new file mode 100644 (file)
index 0000000..da26395
Binary files /dev/null and b/panikweb/static/reglo/RE03-Bold.otf differ
diff --git a/panikweb/static/reglo/RE04-Bold.otf b/panikweb/static/reglo/RE04-Bold.otf
new file mode 100644 (file)
index 0000000..4bcafad
Binary files /dev/null and b/panikweb/static/reglo/RE04-Bold.otf differ
diff --git a/panikweb/static/reglo/RE05-Bold.otf b/panikweb/static/reglo/RE05-Bold.otf
new file mode 100644 (file)
index 0000000..7a990e7
Binary files /dev/null and b/panikweb/static/reglo/RE05-Bold.otf differ
diff --git a/panikweb/static/reglo/RE06.otf b/panikweb/static/reglo/RE06.otf
new file mode 100644 (file)
index 0000000..8d7f564
Binary files /dev/null and b/panikweb/static/reglo/RE06.otf differ
diff --git a/panikweb/static/reglo/RE07-Bold.otf b/panikweb/static/reglo/RE07-Bold.otf
new file mode 100644 (file)
index 0000000..cdd46b5
Binary files /dev/null and b/panikweb/static/reglo/RE07-Bold.otf differ
diff --git a/panikweb/static/reglo/RESYMBOL-resized.otf b/panikweb/static/reglo/RESYMBOL-resized.otf
new file mode 100644 (file)
index 0000000..bb301df
Binary files /dev/null and b/panikweb/static/reglo/RESYMBOL-resized.otf differ
diff --git a/panikweb/static/reglo/RESYMBOL.otf b/panikweb/static/reglo/RESYMBOL.otf
new file mode 100644 (file)
index 0000000..5d22628
Binary files /dev/null and b/panikweb/static/reglo/RESYMBOL.otf differ
diff --git a/panikweb/static/reglo/Reglo-Bold.otf b/panikweb/static/reglo/Reglo-Bold.otf
new file mode 100644 (file)
index 0000000..cb5d4b4
Binary files /dev/null and b/panikweb/static/reglo/Reglo-Bold.otf differ
diff --git a/panikweb/static/reglo/Reglo-Bold.vfb b/panikweb/static/reglo/Reglo-Bold.vfb
new file mode 100644 (file)
index 0000000..590cf11
Binary files /dev/null and b/panikweb/static/reglo/Reglo-Bold.vfb differ
diff --git a/panikweb/static/reglo/RegloScaleBold.otf b/panikweb/static/reglo/RegloScaleBold.otf
new file mode 100644 (file)
index 0000000..ec62742
Binary files /dev/null and b/panikweb/static/reglo/RegloScaleBold.otf differ
diff --git a/panikweb/templates/404.html b/panikweb/templates/404.html
new file mode 100644 (file)
index 0000000..28794a6
--- /dev/null
@@ -0,0 +1,16 @@
+{% extends "base.html" %}
+
+{% block title %}Page non trouvée{% endblock %}
+
+{% block main %}
+
+<div class="wrapper text">
+       <div id="fiber-content" class="padded">
+               <h2>404 / Page non trouvée</h2>
+
+               <p>
+               La page demandée n'a pas été trouvée. Petite larme.
+               </p>
+       </div>
+
+{% endblock %}
diff --git a/panikweb/templates/500.html b/panikweb/templates/500.html
new file mode 100644 (file)
index 0000000..19dc6e4
--- /dev/null
@@ -0,0 +1,18 @@
+{% extends "base.html" %}
+
+{% block title %}Erreur serveur{% endblock %}
+
+{% block main %}
+
+<div class="wrapper text">
+       <div id="fiber-content" class="padded">
+               <h2>500 / Erreur serveur</h2>
+
+               <p>
+               Il y a du pâté (végétarien) dans le serveur.  On essaie de
+               corriger ça rapidement.
+               </p>
+       </div>
+
+{% endblock %}
+
diff --git a/panikweb/templates/agenda.html b/panikweb/templates/agenda.html
new file mode 100644 (file)
index 0000000..a4b1e67
--- /dev/null
@@ -0,0 +1,96 @@
+{% extends "base.html"%}
+{% load paniktags i18n %}
+{% block title %}{% trans 'News' %}{% endblock %}
+{% block toptitle %}
+<h1 class="top"><a class="dimmed" href="{% url 'news' %}">{% trans 'News' %}</a>
+ / <a href="{% url 'agenda' %}">Agenda</a>
+</h1>
+{% endblock %}
+{% block nav %}
+       {% news_nav %}
+{% endblock %}
+{% block main %}
+
+<div class="detail marged news cf">
+       <div class="wrapper navigation">
+{% if month %}
+<h2>{{month|date:"E Y"}}</h2>
+{% else %}
+<p class="intro leftPart">
+Sur les ondes comme dans la ville, une quantité d'événements Panik et proches…
+</p>
+{% endif %}
+
+               <div class="leftPart">
+            <div id="agenda" class="news">
+               {% regroup agenda|dictsort:'event_date' by event_date as agenda_list %}
+                 {% for date in agenda_list %}
+                 <h3>{{ date.grouper|date:"l d E"|lower }}</h3>
+                 {% for content in date.list %}
+                   {% news_inline %}
+                 {% endfor %}
+               {% endfor %}
+               {% if not agenda %}
+                       <div class="big error center">Misère, c'est l'hiver ?!</div>
+               {% endif %}
+
+    <div class="previous-and-next-months">
+<h4>
+    {% if previous_month %}
+        <a href="{% url 'agenda_by_month' year=previous_month.year month=previous_month.month %}"
+           >&lt; {{previous_month|date:'E Y'}}</a>
+    {% endif %}
+    {% if previous_month and next_month %}—{% endif %}
+    {% if next_month %}
+        <a href="{% url 'agenda_by_month' year=next_month.year month=next_month.month %}"
+           >{{next_month|date:'E Y'}} &gt;</a>
+    {% endif %}
+</h4>
+    </div>
+
+            </div>
+               </div>
+               <div class="rightPart">
+                               <div class="sub">
+                                       <h5 class="sectionLabel right">
+                        <a href="{% url 'newsArchives' %}">
+                                           <span class="iconLabel">Toutes</span>
+                                   </a>
+                    </h5>
+                                       <h5 class="sectionLabel">
+                            <span class="iconLabel">{% trans 'Latest News'%}</span>
+                            <a class="button icon-rss inBlock" href="{% url 'rss-feed' %}"></a>
+                    </h5>
+
+
+       <form action="{% url 'newsArchives' %}" id="search-form">
+               <input id="id_q" name="q" type="text" {% if search_query %}value="{{ search_query }}"{% endif %}>
+                <button class="icon-search"><span class="sr-only">{% trans "Search" %}</span></button>
+       </form>
+
+                                               <ul class="custom list newsList">
+                                               {% for content in news|slice:":20" %}
+                                                       <li class="{% if content == newsitem %}current{% endif %}">{% news_inline %}</li>
+                                               {% endfor %}
+                                               </ul>
+                               </div>
+               </div>
+       </div>
+</div>
+{% endblock %}
+{% block links %}
+<div class="wrapper">
+       <div class="padded ">
+               <ul class="news columns padded list custom">
+               {% for NewsItem in newsAll %}
+                       <li class="item ellipsis small  ">
+                       <a href="{% url 'newsitem-view' slug=NewsItem.slug %}">
+                               <span class="title"><strong>{{ NewsItem.date|date:"D d/M" }}</strong>&nbsp;-&nbsp;{{ NewsItem.title }}</span>
+                       </a>
+                       </li>
+               {% endfor %}
+               </ul>
+       </div>
+    </div>
+</div>
+{% endblock %}
diff --git a/panikweb/templates/base.html b/panikweb/templates/base.html
new file mode 100644 (file)
index 0000000..97df707
--- /dev/null
@@ -0,0 +1,88 @@
+{% load gadjo paniktags staticfiles %}<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8" />
+    <title>{{ radio_name }} - {% block title %}{% endblock %}</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="icon" href="{{ STATIC_URL }}img/favicon-16.png" type="image/png" sizes="16x16">
+    <link rel="icon" href="{{ STATIC_URL }}img/favicon-32.png" type="image/png" sizes="32x32">
+    <link rel="icon" href="{{ STATIC_URL }}img/favicon-48.png" type="image/png" sizes="48x48">
+    <link rel="apple-touch-icon" href="{{ STATIC_URL}}img/logo-panik-500-invert.png">
+    <link rel="canonical" href="{{ request.build_absolute_uri }}" />
+
+    <meta name="og:site_name" content="{{ radio_name }}"/>
+    {% block head %}
+    <meta name="description" content="En vous branchant sur le 105.4 FM, vous pénétrerez plus avant dans l'œil du cyclone…" />
+
+    <meta property="og:title" content="{{ radio_long_name }}" />
+    <meta property="og:image" content="{{ site_url }}{% static 'img/Radio_Panik_Logo_2016-01.png' %}" />
+    <meta property="og:description" content="En vous branchant sur le 105.4 FM, vous pénétrerez plus avant dans l'œil du cyclone…" />
+
+    <meta name="twitter:card" content="summary" />
+    <meta name="twitter:title" content="{{ radio_long_name }}" />
+    <meta name="twitter:image" content="{{ site_url }}{% static 'img/Radio_Panik_Logo_2016-01.png' %}" />
+    <meta name="twitter:description" content="En vous branchant sur le 105.4 FM, vous pénétrerez plus avant dans l'œil du cyclone…" />
+
+    {% endblock %}
+
+<link rel="alternate" type="application/rss+xml"  href="{% url 'rss-feed' %}" title="News rss feed">
+<link rel="alternate" type="application/rss+xml"  href="{% url 'atom-feed' %}" title="News atom feed">
+{% block podcasts-feed %}
+<link rel="alternate" type="application/rss+xml"  href="{% url 'podcasts-feed' %}" title="{{ radio_name }} Podcasts">
+{% endblock %}
+
+    <link rel="stylesheet" href="{{ STATIC_URL }}css/style.css?{% start_timestamp %}" type="text/css" />
+
+    <script src="{% xstatic 'jquery' 'jquery.min.js' %}"></script>
+    <script src="{% xstatic 'jquery-ui' 'jquery-ui.min.js' %}"></script>
+    <script src="{{ STATIC_URL }}js/jquery.scrollTo-1.4.3.1-min.js"></script>
+    <script src="{{ STATIC_URL }}js/audioPlayer.js?{% start_timestamp %}"></script>
+    <script src="{{ STATIC_URL }}js/konami.js"></script>
+    <script src="{{ STATIC_URL}}js/strophe.min.js"></script>
+    <script src="{{ STATIC_URL}}js/strophe.muc.js"></script>
+    <script src="{{ STATIC_URL }}js/specifics.js?{% start_timestamp %}"></script>
+
+    {% block extrascripts %}{% endblock %}
+</head>
+
+<body {% block bodyattr %}{% endblock %}>
+       <div id="All">
+               {% block meta %}<div id="metaNav">{% metanav %}</div>{% endblock %}
+               <div id="Commons" class="cf" >
+            <div class="wrapper sided" >
+                <div id="backgroundBox" class="cf">
+                               <a href="{% url 'home' %}" id="mainHeader"><div>
+                                       <h1 class="top" id="radiopanik">{{ radio_long_name }}</h1>
+                               </div></a>
+                               <div id="Player" class="withoutPlaylist">
+                                       {% block listen %}{% player %}{% endblock %}
+                               </div>
+                       </div>
+                   </div>
+               </div>
+               <div id="Changing" class="cf">
+                       {% block toptitle %}{% endblock %}
+                       <div id="Nav" class="cf" >
+                               {% block nav %}{% endblock %}
+                       </div>
+                       <div id="Main" class="cf">
+                               {% block main %}{% endblock %}
+                       </div>
+                       <div id="Related" class="cf">
+                               {% block related %}{% endblock %}
+                       </div>
+               <div id="Footer">
+                       <nav class="wrapper">
+                               <ul>
+                                       <li><a href="/credits/">Crédits</a></li>
+                                       <li><a href="/mentions-legales/">Mentions légales</a></li>
+                               </ul>
+                       </nav>
+               </div>
+               </div>
+               <div id="userLog"></div>
+       </div>
+{% piwik %}
+
+</body>
+</html>
diff --git a/panikweb/templates/chat.html b/panikweb/templates/chat.html
new file mode 100644 (file)
index 0000000..8515330
--- /dev/null
@@ -0,0 +1,83 @@
+{% extends "base.html"%}
+{% load paniktags i18n thumbnail %}
+{% block title %}{% trans 'Chat' %}{% endblock %}
+{% block toptitle %}
+<h1 class="top"><span class="chat {% if emission.image %}with-logo{% endif %}"><a href="{% url 'emission-view' slug=object.slug %}">{{object.title}}</a> - Chat</span></h1>
+{% if emission.image %}
+       {% thumbnail emission.image "120x120" crop="50% 25%" as im %}
+       <div class="top-logo">
+               <img height="120" width="120" src="{{im.url}}"/>
+       </div>
+       {% endthumbnail %}
+{% endif %}
+
+{% endblock %}
+{% block nav %}
+{% endblock %}
+{% block main %}
+
+<div class="wrapper">
+</div>
+<div>
+
+<div class="wrapper navigation chat-page">
+
+       <div class="leftPart chatPart">
+
+       {% if emission.subtitle %}<h3>{{ emission.subtitle }}</h3>{% endif %}
+       {% if emission.text %}
+       <div class="description-emission-chat">
+               {{ emission.text|safe|striptags|truncatewords:75}}
+       </div>
+       {% endif %}
+
+{% if emission.chat_open %}
+
+       <p>
+       Pour réagir en direct et suivre les réactions au cours de l'émission,
+       entrez dans la place !
+       </p>
+
+<div class="chat-area">
+
+<div class="nick">Pseudo ? <input name="nick"> <button>Se connecter</button></div>
+
+<div class="commands" style="display: none;">
+  <span class="prompt">&gt;</span>&nbsp;&nbsp;<input id="msg" name="msg">&nbsp;&nbsp;<button id="send">ok</button>
+</div>
+
+<div id="chat" data-chatroom="{{emission.slug}}">
+</div>
+</div> <!-- .chat-area -->
+{% else %}
+
+<p class="info">
+Ce chat n'est pour le moment pas ouvert.
+</p>
+
+{% endif %}
+
+
+       </div> <!-- .leftPart -->
+
+       <div class="rightPart">
+               <p><b>Quelques règles de bonne conduite quand même.</b></p>
+               <p>
+               Ici comme ailleurs on est des grandes personnes, on évite les
+               propos injurieux, sexistes, homophobes, racistes, etc.
+               </p>
+               <p style="display: none">
+               On garde la violence pour l'état.
+               </p>
+               <p>
+               En cas de problème, n'hésitez pas à contacter le conseil
+               d'administration de la radio, ca-panik@radiopanik.org.
+               </p>
+       </div>
+
+</div>
+</div>
+{% endblock %}
+{% block links %}
+{% endblock %}
+
diff --git a/panikweb/templates/combo/cells/alimentation/episode_auto_selection.html b/panikweb/templates/combo/cells/alimentation/episode_auto_selection.html
new file mode 100644 (file)
index 0000000..d66216c
--- /dev/null
@@ -0,0 +1,34 @@
+{% load paniktags thumbnail staticfiles %}
+{% if title and episodes %}<h3>{{title}}</h3>{% endif %}
+{% for episode in episodes %}
+<div class="episode inline episode-inline">
+       <div class="logo">
+               {% if episode.image %}
+                       {% thumbnail episode.image "60x60" crop="50% 25%" as im %}
+                       <img src="{{im.url}}"/>
+                       {% endthumbnail %}
+               {% elif episode.emission.image %}
+                       {% thumbnail episode.emission.image "60x60" crop="50% 25%" as im %}
+                       <img src="{{im.url}}"/>
+                       {% endthumbnail %}
+               {% else %}
+                       <img class="smooth"  style="width:60px;" src="{% static "img/emission.png" %}"/>
+               {% endif %}
+       </div>
+       <div class="content">
+               {% if episode.main_sound %}
+                       <div class="sound right">{% audio sound=episode.main_sound %}</div>
+               {% endif %}
+               <div class="title">
+                       <h5 class="title">
+                               <a href="{% url 'episode-view' emission_slug=episode.emission.slug slug=episode.slug %}">{{ episode.title }}</a>
+                       </h5>
+               </div>
+               {% if episode.text %}
+               <div class="description">
+                       {{ episode.text|safe|striptags|truncatewords:35 }}
+               </div>
+               {% endif %}
+       </div>
+</div>
+{% endfor %}
diff --git a/panikweb/templates/combo/cells/topik-large/link-cell.html b/panikweb/templates/combo/cells/topik-large/link-cell.html
new file mode 100644 (file)
index 0000000..482ace7
--- /dev/null
@@ -0,0 +1,18 @@
+{% load thumbnail %}
+<div class="topikcellcontent topik-{{cell.link_page.slug}}">
+<a class="block cf" href="{{url}}">
+<span class="logo">
+{% thumbnail cell.link_page.picture "800x450" crop="50% 25%" as im %}
+<div class="logo">
+<img class="normal" src="{{im.url}}"/>
+</div>
+{% endthumbnail %}
+</span>
+<div>
+  <h2>{{title}}</h2>
+  <div class="description">
+    {{cell.link_page.description|safe|striptags}}
+  </div>
+</div>
+</a>
+</div>
diff --git a/panikweb/templates/combo/cells/topik/link-cell.html b/panikweb/templates/combo/cells/topik/link-cell.html
new file mode 100644 (file)
index 0000000..886a490
--- /dev/null
@@ -0,0 +1,18 @@
+{% load thumbnail %}
+<div class="topikcellcontent topik-{{cell.link_page.slug}}">
+<a class="block cf" href="{{url}}">
+<span class="logo">
+{% thumbnail cell.link_page.picture "480x320" crop="50% 25%" as im %}
+<div class="logo">
+<img class="normal" src="{{im.url}}"/>
+</div>
+{% endthumbnail %}
+</span>
+<div>
+  <h5>{{title}}</h5>
+  <div class="description">
+    {{cell.link_page.description|safe|striptags|truncatewords:75}}
+  </div>
+</div>
+</a>
+</div>
diff --git a/panikweb/templates/combo/gallerycell.html b/panikweb/templates/combo/gallerycell.html
new file mode 100644 (file)
index 0000000..49451a9
--- /dev/null
@@ -0,0 +1,28 @@
+{% load thumbnail %}
+{% if cell.title %}<h3>{{ cell.title }}</h3>{% endif %}
+<div class="gallery" id="gallery-{{cell.id}}">
+{% for image in cell.image_set.all %}
+  {% if forloop.first %}
+<div class="first" style="display: none;">
+<img src="#"/>
+<span class="gallery-legend"></span>
+</div>
+<div>
+  {% endif %}
+{% thumbnail image.image "200x100" crop="50% 25%" as im %}
+{% if cell.slug == 'portrait' %}
+{% thumbnail image.image "480x640" crop="50% 25%" as im_large %}
+<span class="image" data-image-large="{{ im_large.url }}"><img src="{{ im.url }}"
+        class="portrait" {% if image.title %} title="{{image.title}}" {% endif %}/></span>
+{% endthumbnail %}
+{% else %}
+{% thumbnail image.image "640x480" crop="50% 25%" as im_large %}
+<span class="image" data-image-large="{{ im_large.url }}"><img src="{{ im.url }}"
+        {% if image.title %} title="{{image.title}}" {% endif %}/></span>
+{% endthumbnail %}
+
+{% endif %}
+{% endthumbnail %}
+{% endfor %}
+</div>
+</div>
diff --git a/panikweb/templates/combo/page_template_about.html b/panikweb/templates/combo/page_template_about.html
new file mode 100644 (file)
index 0000000..40c46a6
--- /dev/null
@@ -0,0 +1,33 @@
+{% extends "base.html" %}
+{% load combo %}
+
+{% block title %}{{ page.title }}{% endblock %}
+
+{% block toptitle %}
+<h1 class="top">À propos</h1>
+{% endblock %}
+
+{% block nav %}
+<div id="About">
+<div class="mainSub">
+           <nav class="distributed">
+                   {% show_menu 0 %}
+           </nav>
+</div>
+</div>
+{% endblock %}
+
+{% block main %}
+
+<div class="wrapper navigation">
+       <div id="fiber-content" class="leftPart">
+               <h2 class="title">{{ page.title }}</h2>
+
+               <div class="text">{% placeholder "content" %}</div>
+       </div>
+       <div id="fiber-nav" class="sub rightPart custom marged">
+               {% block menu %}{% show_menu 1 depth=2 %}{% endblock %}
+       </div>
+</div>
+
+{% endblock %}
diff --git a/panikweb/templates/combo/page_template_full_width.html b/panikweb/templates/combo/page_template_full_width.html
new file mode 100644 (file)
index 0000000..4b3239f
--- /dev/null
@@ -0,0 +1,23 @@
+{% extends "base.html" %}
+{% load combo %}
+
+{% block title %}{{ page.title }}{% endblock %}
+
+{% block toptitle %}
+<h1 class="top fullwidth">{{ page.title }}</h1>
+{% endblock %}
+
+{% block nav %}
+<div id="About">
+</div>
+{% endblock %}
+
+{% block main %}
+
+<div class="wrapper">
+       <div id="fiber-content">
+               <div class="text">{% placeholder "content" %}</div>
+       </div>
+</div>
+
+{% endblock %}
diff --git a/panikweb/templates/combo/page_template_sidebar.html b/panikweb/templates/combo/page_template_sidebar.html
new file mode 100644 (file)
index 0000000..03ceb98
--- /dev/null
@@ -0,0 +1,40 @@
+{% extends "base.html" %}
+{% load combo %}
+
+{% block title %}{{ page.title }}{% endblock %}
+
+{% block toptitle %}
+<h1 class="top bg-title"><a href="{{ page.get_parents_and_self.0.get_online_url }}">{{ page.get_parents_and_self.0.title }}</a></h1>
+{% endblock %}
+
+{% block nav %}
+{% endblock %}
+
+{% block main %}
+
+<div class="wrapper navigation" id="main-{{page.get_parents_and_self.0.slug}}" >
+       <div id="fiber-content" class="leftPart">
+               {% if page.get_parents_and_self.0.title != page.title %}
+               <h1>{{ page.title }}</h1>
+               {% endif %}
+               <div class="text">{% placeholder "content" %}</div>
+       </div>
+       <div class="sub rightPart custom marged">
+               {% placeholder "sidebar" %}
+               <ul class="custom list">
+               {% for page in page.get_parents_and_self.0.get_children %}
+                 {% if page.public and not page.exclude_from_navigation %}
+                   {% if page.has_children and page.slug != "35-ans" %}
+                     {% for subpage in page.get_children %}
+                       {% include "combo/topik_menu_item.html" with page=subpage category=page.title only %}
+                     {% endfor %}
+                   {% else %}
+                     {% include "combo/topik_menu_item.html" with page=page category="Topik" only %}
+                   {% endif %}
+                 {% endif %}
+               {% endfor %}
+               </ul>
+       </div>
+</div>
+
+{% endblock %}
diff --git a/panikweb/templates/combo/topik_menu_item.html b/panikweb/templates/combo/topik_menu_item.html
new file mode 100644 (file)
index 0000000..55a7028
--- /dev/null
@@ -0,0 +1,24 @@
+{% load combo paniktags thumbnail %}
+<li class="item">
+  <div class="topik inline cf">
+    <a class="block cf topik-link" href="{{page.get_online_url}}">
+    <div class="logo">
+        {% if page.picture %}
+          {% thumbnail page.picture "60x60" crop="50% 25%" as im %}
+          <img alt="" width="60" height="60" src="{{im.url}}"/>
+          {% endthumbnail %}
+        {% else %}
+          <img alt="" src="/static/img/sound.png" width="60" height="60">
+        {% endif %}
+    </div>
+    <div class="content">
+      <div class="title">
+        <h5 class="title">{{page.title}}</h5>
+      </div>
+      <div class="smooth metas">
+        <span class="categories">{{category}}</span>
+      </div>
+    </div>
+    </a>
+  </div>
+</li>
diff --git a/panikweb/templates/emissions.html b/panikweb/templates/emissions.html
new file mode 100644 (file)
index 0000000..21e9d09
--- /dev/null
@@ -0,0 +1,24 @@
+{% extends "base.html" %}
+{% load paniktags i18n %}
+{% block bodyID %}Emissions{% endblock %}
+{% block title %}Émissions{% endblock %}
+{% block toptitle %}
+<h1 class="top"><a href="{% url 'grid' %}">{% trans 'Program' %}</a></h1>
+{% endblock %}
+{% block nav %}
+       {% emission_nav with klass="emissions" %}
+       <span class="bg-title" style="display: none"><a>{% trans 'Emissions' %}</a></span>
+{% endblock %}
+{% block main %}
+<div class="emissions">
+
+       <div class="wrapper">
+               <ul class="custom list columns padded">
+               {% for emission in emissions %}
+                       <li class="item {% for category in emission.categories.all %} {{ category|slugify }}{% endfor %}{% if emission.archived %} archived{% endif %}"
+                       >{% emission_resume %}</li>
+               {% endfor %}
+               </ul>
+       </div>
+</div>
+{% endblock %}
diff --git a/panikweb/templates/emissions/archives.html b/panikweb/templates/emissions/archives.html
new file mode 100644 (file)
index 0000000..300a3e2
--- /dev/null
@@ -0,0 +1,11 @@
+{% extends "emissions.html" %}
+{% load paniktags i18n%}
+{% block bodyID %}Emissions{% endblock %}
+{% block title %}Archives{% endblock %}
+{% block toptitle %}
+<h1 class="top"><a href="{% url 'grid' %}">{% trans 'Program' %}</a></h1>
+{% endblock %}
+{% block nav %}
+       {% emission_nav with klass="archives" %}
+       <span class="bg-title" style="display: none"><a>{% trans 'Archives' %}</a></span>
+{% endblock %}
diff --git a/panikweb/templates/emissions/detail.html b/panikweb/templates/emissions/detail.html
new file mode 100644 (file)
index 0000000..36e037c
--- /dev/null
@@ -0,0 +1,49 @@
+{% load i18n paniktags %}
+<div class="emission emission-detail cf">
+       <article class="text userContent">
+       {% if schedules or emission.subtitle %}
+       <div class="metas marged">
+               {% if schedules %}
+                       <ul class="schedule custom">
+                               {% for schedule in schedules %}
+                               <li>
+                                       <span class="label">{{ schedule.datetime|date:"l G:i" }}</span>
+                                       {% if schedule.weeks_string %}
+                                       <span class="weekdiff">({{ schedule.weeks_string }})</span>
+                                       {% endif %}
+                                       {% if schedule.rerun %} <span class="smooth">(rediff)</span> {% endif %}
+                               </li>
+                               {% endfor %}
+                       </ul>
+               {% endif %}
+               {% if emission.subtitle %}
+               <h4 class="subtitle">{{ emission.subtitle }}</h4>
+               {% endif %}
+       </div>
+       {% endif %}
+       {% if emission.image %}
+               <div class="emission-logo"><img class="logo" src="{{ emission.image.url }}"/></div>
+       {% endif %}
+
+       {% if emission.text %}
+               {{ emission.text|safe}}
+       {% endif %}
+       </article>
+       {% if emission.email or emission.website %}
+       <div class="contacts box">
+               {% if emission.email %}
+                       <div class="email ellipsis">
+                               <span class="icon-envelope"></span>
+                               <span>{{ emission.email|strreplace:"@, (AT) "|strreplace:"., (DOT) "}}</span>
+                       </div>
+               {% endif %}
+               {% if emission.website %}
+                       <div class="contact ellipsis">
+                               <span class="icon-globe"></span>
+                               <a href="{{ emission.website}}">{{ emission.website}}</a>
+                       </div>
+               {% endif %}
+       </div>
+       {% endif %}
+</div>
+
diff --git a/panikweb/templates/emissions/emission_detail.html b/panikweb/templates/emissions/emission_detail.html
new file mode 100644 (file)
index 0000000..226dd17
--- /dev/null
@@ -0,0 +1,129 @@
+{% extends "emissions.html" %}
+{% load paniktags staticfiles i18n thumbnail %}
+{% block bodyID %}Emissions{% endblock %}
+{% block title %}{{ emission.title }}{% endblock %}
+
+{% block head %}
+<meta property="og:title" content="{{ emission.title }}" />
+<meta name="twitter:title" content="{{ emission.title }}" />
+{% if emission.image %}
+<meta name="twitter:card" content="summary_large_image">
+<meta property="og:image" content="{{ site_url }}{{ emission.image.url }}" />
+<meta name="twitter:image" content="{{ site_url }}{{ emission.image.url }}" />
+{% else %}
+<meta name="twitter:card" content="summary">
+<meta property="og:image" content="{{ site_url }}{% static 'img/Radio_Panik_Logo_2016-01.png' %}" />
+<meta name="twitter:image" content="{{ site_url }}{% static 'img/Radio_Panik_Logo_2016-01.png' %}" />
+{% endif %}
+{% if emission.subtitle %}
+<meta property="og:description" content="{{ emission.subtitle }}" />
+<meta name="twitter:description" content="{{ emission.subtitle }}" />
+{% else %}
+<meta property="og:description" content="{{ emission.text|safe|striptags|truncatewords:75 }}"/>
+<meta name="twitter:description" content="{{ emission.text|safe|striptags|truncatewords:75 }}"/>
+{% endif %}
+{% endblock %}
+
+{% block podcasts-feed %}
+<link rel="alternate" type="application/rss+xml" href="{% url 'emission-podcasts' slug=emission.slug %}" title="{{ emission.title }} Podcasts">
+{% endblock %}
+
+{% block toptitle %}
+<h1 class="top"><a href="{% url 'grid' %}">{% trans 'Program' %}</a></h1>
+{% endblock %}
+{% block nav %}
+       {% emission_nav %}
+{% endblock %}
+{% block main %}
+<div class="wrapper navigation cf">
+       <div id="Emission-container" class="emission">
+               <div data-tabbed="true" id="Emission-tabs-default">
+                       <div id="Emission-tabs-detail" class="leftPart">
+                               {% if episode %}
+                                       {% episode_detail %} 
+                               {% else %}
+                                       {% emission_detail %}
+                               {% endif %}
+                       </div>
+
+               {% if episodes.exists or futurEpisodes.exists or news or nonstop %}
+                       <div id="Emission-tabs-menu" class="rightPart episodes">
+
+                               {% if news %}
+                                       <div class="sub emissions-newsitems">
+                                               <h5 class="sectionLabel">{% trans 'News' %}</h5>
+                                               <ul class="custom list">
+                                               {% for content in news %}
+                                                       <li>{% news_inline %}</li>
+                                               {% endfor %}
+                                               </ul>
+                                       </div>
+                               {% endif %}
+
+                       {% if episodes.exists or futurEpisodes.exists %}
+                        <h5 class="sectionLabel right"><a class="" href="{% url 'emissionEpisodes' slug=emission.slug %}">Tous ({{ episodes.count }})</a></h5>
+                                               <h5 class="sectionLabel">Épisodes&nbsp;<a title="Podcasts" class="button icon-rss inBlock" href="{% url 'emission-podcasts' slug=emission.slug%}"></a></h5>
+                    <form method="get" action="{% url 'emissionEpisodes' slug=emission.slug %}" class="" id="search-form">
+                                <input id="id_q" name="q" type="text" {% if search_query %}value="{{ search_query }}"{% endif %}>
+                                <button class="icon-search"><span class="sr-only">{% trans "Search" %}</span></button>
+                        </form>
+
+                               {% if futurEpisodes %}
+                                       <div class="sub futur-episodes">
+                                               <h5 class="sectionLabel">{% trans 'Coming Soon' %}</h5>
+                                               {% for episode in futurEpisodes|slice:":3" %}
+                                                       {% episode_inline %}
+                                               {% endfor %}
+                                       </div>
+                               {% endif %}
+
+                               {% if episodes %}
+                                       <div class="sub recent-episodes">
+                                               <h5 class="sectionLabel">{% trans 'Previously' %}</h5>
+
+                                               {% with episodes|slice:"0:5" as episodes %}
+                                                       {% for episode in episodes %}
+                                                               {% episode_inline %}
+                                                       {% endfor %}
+                                               {% endwith %}
+                                       </div>
+                               {% endif %}
+                       {% endif %}
+
+                       {% if nonstop %}
+                               <div class="sub emissions-newsitems">
+                                       <h5 class="sectionLabel">{% trans 'Recently' %}</h5>
+                                       <ul class="custom list">
+                                       {% for date in nonstop_dates %}
+                                       <li><div class="content content-inline inline cf">
+                                       <a class="block cf" href="{% url 'nonstop-playlist' slug=emission.slug year=date.year month=date.month day=date.day %}">
+                                       {% if emission.image %}
+                                       {% thumbnail emission.image "60x60" crop="50% 25%" as im %}
+                                       <div class="logo">
+                                       <img alt="" class="left" height="60" width="60" src="{{im.url}}"/>
+                                       </div>
+                                       {% endthumbnail %}
+                                       {% endif %}
+                                       <div class="content">
+                                               <h5 class="title">{{date|date:'D d M Y'|lower}}</h5>
+                                       </div>
+                                       <div class="smooth">Playlist</div>
+                                       </a></li>
+                                       {% endfor %}
+                                       </ul>
+                               </div>
+                       {% endif %}
+
+                       </div>
+               {% endif %}
+               </div>
+       </div>
+</div>
+{% endblock %}
+
+{% block links %}
+{% endblock %}
+
+{% block related %}
+{% related_objects object=emission %}
+{% endblock %}
diff --git a/panikweb/templates/emissions/episode_detail.html b/panikweb/templates/emissions/episode_detail.html
new file mode 100644 (file)
index 0000000..dc4f362
--- /dev/null
@@ -0,0 +1,36 @@
+{% extends "emissions/emission_detail.html" %}
+{% load paniktags staticfiles soundfiles %}
+{% block title %}{{ episode.title }} - {{ episode.emission.title }} {% endblock %}
+
+{% block head %}
+<meta property="og:title" content="{{ episode.emission.title }} - {{ episode.title }}" />
+<meta name="twitter:title" content="{{ episode.emission.title }} - {{ episode.title }}" />
+{% if episode.image %}
+<meta name="twitter:card" content="summary_large_image">
+<meta property="og:image" content="{{ site_url }}{{ episode.image.url }}" />
+<meta name="twitter:image" content="{{ site_url }}{{ episode.image.url }}" />
+{% elif episode.emission.image %}
+<meta name="twitter:card" content="summary_large_image">
+<meta property="og:image" content="{{ site_url }}{{ episode.emission.image.url }}" />
+<meta name="twitter:image" content="{{ site_url }}{{ episode.emission.image.url }}" />
+{% else %}
+<meta name="twitter:card" content="summary">
+<meta property="og:image" content="{{ site_url }}{% static 'img/Radio_Panik_Logo_2016-01.png' %}" />
+<meta name="twitter:image" content="{{ site_url }}{% static 'img/Radio_Panik_Logo_2016-01.png' %}" />
+{% endif %}
+{% if episode.subtitle %}
+<meta property="og:description" content="{{ episode.subtitle }}" />
+<meta name="twitter:description" content="{{ episode.subtitle }}" />
+{% else %}
+<meta property="og:description" content="{{ episode.text|safe|striptags|truncatewords:75 }}"/>
+<meta name="twitter:description" content="{{ episode.text|safe|striptags|truncatewords:75 }}"/>
+{% endif %}
+{% if episode.main_sound %}
+<meta property="og:audio" content="{{ site_url }}{{ episode.main_sound|format_url:'ogg' }}"/>
+<meta property="og:audio:type" content="audio/ogg"/>
+{% endif %}
+{% endblock %}
+
+{% block related %}
+{% related_objects object=episode %}
+{% endblock %}
diff --git a/panikweb/templates/emissions/episodes.html b/panikweb/templates/emissions/episodes.html
new file mode 100644 (file)
index 0000000..5bcae80
--- /dev/null
@@ -0,0 +1,49 @@
+{% extends "emissions/emission_detail.html" %}
+{% load paniktags %}
+{% block nav %}
+       {% emission_nav klass "episodes" %}
+{% endblock %}
+
+{% block main %}
+<div class="wrapper {% if episodes %}sided{% endif %}">
+
+       {% if search_query and not episodes %}
+                       <div class="big error padded center">Manque de pot, pas de résultats à cette recherche !</div>
+       {% endif %}
+
+       {% if search_query and episodes or episodes.count <= 24 %}
+               <ul class="custom columns list">
+               {% for episode in episodes %}
+                       <li class="item {% for category in episode.emission.categories.all %} {{ category|slugify }}{% endfor %}">
+                               {% episode_resume model="inline"%}                      
+                       </li>
+               {% endfor %}
+               </ul>
+       {% else %}
+       <div id="Emission-container" class="emission padded">
+               {% if episodes %}
+                       {% with episodes as episodes %}
+                               {% regroup episodes by first_diffusion|date:"F Y"|capfirst as month_list %}
+                               <div>
+                               {% for month in month_list %}
+                                       <div class="monthGroup {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}">
+                                               <div 
+                                                       class="legend button"                                           
+                                                       onclick="$('#{{ month.grouper|slugify }}').toggle();"
+                                               >&gt; {{ month.grouper }}</div>
+                                               <ul class="custom list" id="{{ month.grouper|slugify }}" 
+                                                       {% if forloop.counter >= 3 %}style="display:none;"{% endif %}
+                                               >
+                                               {% for episode in month.list %}
+                                                       <li>{% episode_resume model="inline" date="daytime" %}</li>
+                                               {% endfor %}
+                                               </ul>
+                                       </div>
+                               {% endfor %}
+                               </div>
+                       {% endwith %}
+               {% endif %}
+       </div>
+       {% endif %}
+</div>
+{% endblock %}
diff --git a/panikweb/templates/emissions/nav.html b/panikweb/templates/emissions/nav.html
new file mode 100644 (file)
index 0000000..e9fd833
--- /dev/null
@@ -0,0 +1,56 @@
+{% load i18n %}
+
+<div class="mainSub">
+    <div>
+           <nav>
+                   <ul class="inline padded">
+                           <li><a href="{% url 'grid' %}" class="{% if class == "grid" %}active{% endif %}">
+                                   <span class="iconLabel">{% trans 'Grid' %}</span>
+                           </a></li>
+                           <li><a href="{% url 'program' %}" class="{% if class == "program" %}active{% endif %}">
+                                   <span class="iconLabel">{% trans 'By Week' %}</span>
+                           </a></li>
+                           <li><a href="{% url 'emissions' %}" class="{% if class != "program" and class != "grid" and class != "archives" %}active{% endif %}">
+                                   <span class="iconLabel">{% trans 'Emissions' %}</span>
+                           </a></li>
+                           <li><a href="{% url 'emissionsArchives' %}" class="{% if class == "archives" %}active{% endif %}">
+                                   <span class="iconLabel">{% trans 'Archives' %}</span>
+                           </a></li>
+                   </ul>
+           </nav>
+    </div>
+</div>
+{% if categories %}
+<div>
+               <nav id="gridNav" class="checkable">
+                       <ul class="by{{ categories.count }}">
+                       {% for category in categories %}
+                               {% if class == "grid" %}
+                                       <li><button class="check icon-check-empty" data-about="#Main" data-highlight=".{{ category|slugify }}"><span class="category">{{ category }}</span></button></li>
+                               {% else %}
+                                       <li><button class="check icon-check-empty" data-about="#Main" data-toggle=".{{ category|slugify }}"><span class="category">{{ category }}</span></button></li>
+                               {% endif %}
+                       {% endfor %}
+                       </ul>
+               </nav>
+</div>
+{% endif %}
+{% if emission %}
+<div class="navigation">
+       <header class="mainHeader marged cf">
+            <div class="leftPart">
+                       <h2 class="squashed title bg-title">
+                               <a href="{% url 'emission-view' slug=emission.slug %}">{{ emission.title }}</a>
+                       </h2>
+               {% if emission.categories %}
+                       <div class="categories">
+                       {% for category in emission.categories.all %}
+                               <a href="{% url 'emissions' %}?q={{category.slug}}"><span class="category">{{category}}</span></a>
+                       {% endfor%}
+                       </div>
+               {% endif %}
+            </div>
+           </header>
+</div>
+
+{% endif %}
diff --git a/panikweb/templates/emissions/newsitem_detail.html b/panikweb/templates/emissions/newsitem_detail.html
new file mode 100644 (file)
index 0000000..ed46904
--- /dev/null
@@ -0,0 +1,99 @@
+{% extends "news.html" %}
+{% load i18n staticfiles paniktags %}
+{% block title %}{{ newsitem.title }}{% endblock %}
+
+{% block toptitle %}
+<h1 class="top"><a href="{% url 'news' %}">{% trans 'News' %}</a></h1>
+{% endblock %}
+
+{% block head %}
+<meta property="og:title" content="{{ newsitem.title }}" />
+<meta name="twitter:title" content="{{ newsitem.title }}" />
+<meta property="og:description" content="{{ newsitem.text|safe|striptags|truncatewords:75 }}"/>
+<meta name="twitter:description" content="{{ newsitem.text|safe|striptags|truncatewords:75 }}"/>
+{% if newsitem.image %}
+<meta name="twitter:card" content="summary_large_image">
+<meta property="og:image" content="{{ site_url }}{{ newsitem.image.url }}" />
+<meta name="twitter:image" content="{{ site_url }}{{ newsitem.image.url }}" />
+{% else %}
+<meta name="twitter:card" content="summary">
+<meta property="og:image" content="{{ site_url }}% static 'img/Radio_Panik_Logo_2016-01.png' %}" />
+<meta name="twitter:image" content="{{ site_url }}{% static 'img/Radio_Panik_Logo_2016-01.png' %}" />
+{% endif %}
+{% endblock %}
+
+
+{% block main %}
+<div class="detail news cf">
+       <div class="wrapper navigation">
+               <div class="leftPart">
+                       <header>
+                               <h2 class="squashed title">
+                                       {{ newsitem.title }}
+                               </h2>
+{% if newsitem.event_date %}
+<div class="date cf label">{{ newsitem.event_date|date:'D d M Y'|lower }}</div>
+{% endif %}
+                               {% if newsitem.date %}
+                                       <div class="date cf label smooth publication-date">Publiée le {{ newsitem.date|date:"D d M Y"|lower }}</div>
+                               {% endif %}
+                       </header>
+                       {% if newsitem.image %}
+                               <img class="logo right button" onclick="$(this).toggleClass('right marged');" src="{{ newsitem.image.url }}"/>
+                       {% endif %}
+                       <div class="userContent description">   
+                               {{ newsitem.text|safe}}
+                       </div>
+
+{% block topik %}
+{% for topik in topik_pages %}
+  {% topik topik=topik %}
+{% endfor %}
+{% endblock %}
+
+                       {% if newsitem.tags.all %}
+                       <ul class="custom inline tags">
+                               {% for tag in newsitem.tags.all %}
+                               <li><a class="tag" href="{% url 'search' %}?&selected_facets=tags_exact:{{tag|facet_tag}}">{{ tag }}</a></li>
+                               {% endfor %}
+                       </ul>
+                       {% endif %}
+
+               </div>
+               <div class="rightPart">
+                               <div class="sub">
+                       {% if newsitem.emission %}
+                                   <h5 class="sectionLabel">proposé par</h5>
+                                   {% with newsitem.emission as emission %}
+                                           <div class="">{% emission_resume %}</div>
+                                   {% endwith %}
+                       {% endif %}
+                                       <h5 class="sectionLabel right">
+                        <a href="{% url 'newsArchives' %}">
+                                           <span class="iconLabel">Toutes</span>
+                                   </a>
+                    </h5>
+                                       <h5 class="sectionLabel">
+                            <span class="iconLabel">Dernières actus</span>
+                    </h5>
+
+
+       <form action="{% url 'newsArchives' %}" id="search-form">
+               <input id="id_q" name="q" type="text" {% if search_query %}value="{{ search_query }}"{% endif %}>
+                <button class="icon-search"><span class="sr-only">{% trans "Search" %}</span></button>
+       </form>
+
+                                               <ul class="custom list newsList">
+                                               {% for content in news|slice:":10" %}
+                                                       <li class="{% if content == newsitem %}current{% endif %}">{% news_inline %}</li>
+                                               {% endfor %}
+                                               </ul>
+                               </div>
+               </div>
+       </div>
+</div>
+{% endblock %}
+
+{% block related %}
+{% related_objects object=newsitem %}
+{% endblock %}
diff --git a/panikweb/templates/emissions/resume.html b/panikweb/templates/emissions/resume.html
new file mode 100644 (file)
index 0000000..df832fe
--- /dev/null
@@ -0,0 +1,39 @@
+{% load thumbnail staticfiles %}
+<div class="emission emission-resume resume cf">
+       <div class="{% if emission.archived %}archived{% endif %}">
+               <a class="block" href="{% url 'emission-view' slug=emission.slug %}">
+                       <div class="logo left">
+                               {% if emission.image %}
+                                       {% thumbnail emission.image "60x60" crop="50% 25%" as im %}
+                                       <img alt="" width="60" height="60" src="{{im.url}}"/>
+                                       {% endthumbnail %}
+                               {% else %}
+                                       <img alt="" class="smooth"  style="width:60px;" src="{% static "img/emission.png" %}"/>
+                               {% endif %}
+                       </div>
+                       <div class="title">
+                               <h5>
+                                       {{ emission.title }}
+                               </h5>
+                               <div class="smooth metas">
+                               {% if emission.categories %}
+                                       <span class="categories">
+                                       {% for category in emission.categories.all %}
+                                               {% if forloop.counter > 1 %} - {% endif %}<span class="category">{{category}}</span>
+                                       {% endfor%}
+                                       </span>
+                               {% endif %}
+                               </div>
+                       </div>
+                       {% if emission.subtitle %}
+                               <div class="description">
+                                       {{ emission.subtitle }}
+                               </div>
+                       {% elif emission.text %}
+                               <div class="description">
+                                       {{ emission.text|safe|striptags|truncatewords:20}}
+                               </div>
+                       {% endif %}
+               </a>
+       </div>
+</div>
diff --git a/panikweb/templates/emissions/search_result.html b/panikweb/templates/emissions/search_result.html
new file mode 100644 (file)
index 0000000..f1f343e
--- /dev/null
@@ -0,0 +1,6 @@
+<a href="{% url 'emission-view' slug=result.slug %}">
+       <span class="icon-microphone" ></span>
+       <strong>{{ result.title }}</strong>
+       <br />
+       <span>{% if result.subtitle %}{{ result.subtitle }}{% else %} {% endif %}</span>
+</a>
diff --git a/panikweb/templates/episodes/detail.html b/panikweb/templates/episodes/detail.html
new file mode 100644 (file)
index 0000000..80d8c69
--- /dev/null
@@ -0,0 +1,93 @@
+{% load thumbnail paniktags %}
+<div class="episode detail episode-detail cf">
+       {% if episode.first_diffusion %}
+       <div class="dateBloc">
+               <div class="date">
+                       <div class="day">
+                           {{ episode.first_diffusion|date:"D"|slice:":2"}}
+                       </div>
+                       <div class="number">
+                           {{ episode.first_diffusion|date:"d" }}
+                       </div>
+                       {% if date != "daytime" %}
+                       <div class="month">
+                           {{ episode.first_diffusion|date:"M y" }}
+                       </div>
+                       {% endif %}
+                       <div class="time">
+                           {{ episode.first_diffusion|date:"H:i" }}
+                       </div>
+               </div>
+       </div>
+       {% endif %}
+       {% if diffusions %}
+       <header class="">
+               <h3 class="">{{ episode.title }}</h3>
+               {% if episode.subtitle %}
+               <h3 class="episode-subtitle">{{ episode.subtitle }}</h3>
+               {% endif %}
+               {% if diffusions|length > 1 %}
+               <div class="label">Diffusions</div>
+               {% else %}
+               <div class="label">Diffusion</div>
+               {% endif %}
+               <ul class="diffusions custom">
+                       {% for schedule in diffusions %}
+                               <li><span class="date">{{ schedule.datetime|date:"l d M Y à H:i" }}</span></li>
+                       {% endfor %}
+               </ul>
+       </header>
+       {% endif %}
+       {% if episode.main_sound %}
+               <div class="sound">
+                       {% audio sound=episode.main_sound %}
+               </div>
+       {% endif %}
+       <div class=&quo