@ -0,0 +1,10 @@
|
||||
# EditorConfig is awesome: http://EditorConfig.org |
||||
|
||||
# top-most EditorConfig file |
||||
root = true |
||||
|
||||
# Unix-style newlines with a newline ending every file |
||||
[*] |
||||
end_of_line = lf |
||||
insert_final_newline = true |
||||
indent_style = tab |
@ -0,0 +1,219 @@
|
||||
Ext.define('Rambox.view.add.Add',{ |
||||
extend: 'Ext.window.Window' |
||||
|
||||
,requires: [ |
||||
'Rambox.view.add.AddController' |
||||
,'Rambox.view.add.AddModel' |
||||
] |
||||
|
||||
,controller: 'add-add' |
||||
,viewModel: { |
||||
type: 'add-add' |
||||
} |
||||
|
||||
// private
|
||||
,record: null |
||||
,service: null |
||||
,edit: false |
||||
|
||||
// defaults
|
||||
,modal: true |
||||
,width: 500 |
||||
,autoShow: true |
||||
,resizable: false |
||||
,draggable: false |
||||
,bodyPadding: 20 |
||||
|
||||
,initComponent: function() { |
||||
var me = this; |
||||
|
||||
me.title = (!me.edit ? 'Add ' : 'Edit ') + me.record.get('name'); |
||||
me.icon = me.record.get('type') === 'custom' ? (!me.edit ? 'resources/icons/custom.png' : (me.record.get('logo') === '' ? 'resources/icons/custom.png' : me.record.get('logo'))) : 'resources/icons/'+me.record.get('logo'); |
||||
me.items = [ |
||||
{ |
||||
xtype: 'form' |
||||
,items: [ |
||||
{ |
||||
xtype: 'textfield' |
||||
,fieldLabel: 'Name' |
||||
,value: me.record.get('type') === 'custom' ? (me.edit ? me.record.get('name') : '') : me.record.get('name') |
||||
,name: 'serviceName' |
||||
,allowBlank: true |
||||
,listeners: { specialkey: 'onEnter' } |
||||
} |
||||
,{ |
||||
xtype: 'container' |
||||
,layout: 'column' |
||||
,hidden: me.edit ? me.service.get('url').indexOf('___') === -1 && !me.service.get('custom_domain') : me.record.get('url').indexOf('___') === -1 && !me.record.get('custom_domain') |
||||
,items: [ |
||||
{ |
||||
xtype: 'textfield' |
||||
,fieldLabel: 'URL' |
||||
,name: 'url' |
||||
,value: me.edit && me.service.get('url').indexOf('___') >= 0 ? me.record.get('url').replace(me.service.get('url').split('___')[0], '').replace(me.service.get('url').split('___')[1], '') : (me.record.get('url').indexOf('___') === -1 ? me.record.get('url') : '') |
||||
,readOnly: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? true : me.service.get('url').indexOf('___') === -1 && !me.service.get('custom_domain')) : me.record.get('url').indexOf('___') === -1 && me.record.get('custom_domain') |
||||
,allowBlank: false |
||||
,submitEmptyText: false |
||||
,emptyText: me.record.get('url') === '___' ? 'http://' : '' |
||||
,vtype: me.record.get('url') === '___' ? 'url' : '' |
||||
,width: 275 |
||||
,listeners: { specialkey: 'onEnter' } |
||||
} |
||||
,{ |
||||
xtype: 'cycle' |
||||
,showText: true |
||||
,style: 'border-top-left-radius:0;border-bottom-left-radius:0;' |
||||
,hidden: me.edit ? me.service.get('type') === 'custom' || me.service.get('url') === '___' : me.record.get('type') === 'custom' || me.record.get('url') === '___' |
||||
,arrowVisible: me.edit ? (me.service.get('url').indexOf('___') >= 0 && !me.service.get('custom_domain') ? false : me.service.get('custom_domain')) : (me.record.get('url').indexOf('___') >= 0 && !me.record.get('custom_domain') ? false : me.record.get('custom_domain')) |
||||
,menu: { |
||||
items: [ |
||||
{ |
||||
text: me.edit ? (me.service.get('url').indexOf('___') === -1 ? 'Official Server' : Ext.String.endsWith(me.service.get('url'), '/') ? me.service.get('url').split('___')[1].slice(0, -1) : me.service.get('url').split('___')[1]) : (me.record.get('url').indexOf('___') === -1 ? 'Official Server' : Ext.String.endsWith(me.record.get('url'), '/') ? me.record.get('url').split('___')[1].slice(0, -1) : me.record.get('url').split('___')[1]) |
||||
,checked: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? true : Ext.String.endsWith(me.record.get('url'), me.service.get('url').split('___')[1])) : true |
||||
,disabled: me.edit ? me.service.get('url') === '___' : me.record.get('url') === '___' |
||||
} |
||||
,{ |
||||
text: 'Custom Server' |
||||
,checked: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? false : !Ext.String.endsWith(me.record.get('url'), me.service.get('url').split('___')[1])) : false |
||||
,custom: true |
||||
,disabled: me.edit ? !me.service.get('custom_domain') : !me.record.get('custom_domain') |
||||
} |
||||
] |
||||
} |
||||
// Fixes bug EXTJS-20094 for version Ext JS 5
|
||||
,arrowHandler: function(cycleBtn, e) { |
||||
if ( !cycleBtn.arrowVisible ) cycleBtn.hideMenu(); |
||||
} |
||||
,changeHandler: function(cycleBtn, activeItem) { |
||||
Ext.apply(cycleBtn.previousSibling(), { |
||||
emptyText: activeItem.custom ? 'http://' : ' ' |
||||
,vtype: activeItem.custom ? 'url' : '' |
||||
}); |
||||
cycleBtn.previousSibling().applyEmptyText(); |
||||
cycleBtn.previousSibling().reset(); |
||||
|
||||
if ( me.edit && cycleBtn.nextSibling().originalValue !== '2' ) { |
||||
me.service.get('custom_domain') && !activeItem.custom ? cycleBtn.previousSibling().reset() : cycleBtn.previousSibling().setValue(''); |
||||
} else if ( me.edit && cycleBtn.nextSibling().originalValue === '2' ) { |
||||
me.service.get('custom_domain') && !activeItem.custom ? cycleBtn.previousSibling().setValue( me.service.get('url').indexOf('___') === -1 && me.service.get('custom_domain') ? me.service.get('url') : '') : cycleBtn.previousSibling().reset(); |
||||
} else if ( !me.edit && cycleBtn.nextSibling().originalValue === '1' ) { |
||||
activeItem.custom ? cycleBtn.previousSibling().setValue('') : cycleBtn.previousSibling().reset(); |
||||
} |
||||
|
||||
cycleBtn.previousSibling().setReadOnly( activeItem.custom ? false : (me.edit ? me.service.get('url').indexOf('___') === -1 : me.record.get('url').indexOf('___') === -1) ); |
||||
cycleBtn.nextSibling().setValue( activeItem.custom ? 2 : 1 ); |
||||
} |
||||
} |
||||
,{ |
||||
xtype: 'hiddenfield' |
||||
,name: 'cycleValue' |
||||
,value: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? 1 : (!Ext.String.endsWith(me.record.get('url'), me.service.get('url').split('___')[1]) ? 2 : 1)) : 1 |
||||
} |
||||
] |
||||
} |
||||
,{ |
||||
xtype: 'textfield' |
||||
,fieldLabel: 'Logo' |
||||
,emptyText: 'http://url.com/image.png' |
||||
,name: 'logo' |
||||
,vtype: me.record.get('type') === 'custom' ? 'url' : '' |
||||
,value: me.record.get('type') === 'custom' ? (me.edit ? me.record.get('logo') : '') : me.record.get('logo') |
||||
,allowBlank: true |
||||
,hidden: me.record.get('type') !== 'custom' |
||||
,margin: '5 0 0 0' |
||||
,listeners: { specialkey: 'onEnter' } |
||||
} |
||||
,{ |
||||
xtype: 'fieldset' |
||||
,title: 'Options' |
||||
,margin: '10 0 0 0' |
||||
,items: [ |
||||
{ |
||||
xtype: 'checkbox' |
||||
,boxLabel: 'Align to Right' |
||||
,checked: me.edit ? (me.record.get('align') === 'right' ? true : false) : false |
||||
,name: 'align' |
||||
,uncheckedValue: 'left' |
||||
,inputValue: 'right' |
||||
} |
||||
,{ |
||||
xtype: 'checkbox' |
||||
,boxLabel: 'Show notifications' |
||||
,name: 'notifications' |
||||
,checked: me.edit ? me.record.get('notifications') : true |
||||
,uncheckedValue: false |
||||
,inputValue: true |
||||
} |
||||
,{ |
||||
xtype: 'checkbox' |
||||
,boxLabel: 'Mute all sounds' |
||||
,name: 'muted' |
||||
,checked: me.edit ? me.record.get('muted') : false |
||||
,uncheckedValue: false |
||||
,inputValue: true |
||||
} |
||||
,{ |
||||
xtype: 'checkbox' |
||||
,boxLabel: 'Trust invalid authority certificates' |
||||
,name: 'trust' |
||||
,hidden: me.record.get('type') !== 'custom' |
||||
,checked: me.edit ? me.record.get('trust') : false |
||||
,uncheckedValue: false |
||||
,inputValue: true |
||||
} |
||||
] |
||||
} |
||||
,{ |
||||
xtype: 'fieldset' |
||||
,title: 'Advanced' |
||||
,margin: '10 0 0 0' |
||||
,collapsible: true |
||||
,collapsed: true |
||||
,items: [ |
||||
{ |
||||
xtype: 'textarea' |
||||
,fieldLabel: 'Custom Code (<a href="https://github.com/saenzramiro/rambox/wiki/Inject-JavaScript-Code" target="_blank">read more</a>)' |
||||
,allowBlank: true |
||||
,name: 'js_unread' |
||||
,value: me.edit ? me.record.get('js_unread') : '' |
||||
,anchor: '100%' |
||||
,height: 120 |
||||
} |
||||
] |
||||
} |
||||
,{ |
||||
xtype: 'container' |
||||
,hidden: (me.edit ? Ext.getStore('ServicesList').getById(me.record.get('type')).get('note') === '' : me.record.get('note') === '') |
||||
,data: { note: (me.edit ? Ext.getStore('ServicesList').getById(me.record.get('type')).get('note') : me.record.get('note')) } |
||||
,margin: '10 0 0 0' |
||||
,style: 'background-color:#93CFE0;color:#053767;border-radius:6px;' |
||||
,tpl: [ |
||||
'<i class="fa fa-info-circle" aria-hidden="true" style="font-size:40px;margin:20px;"></i>' |
||||
,'<span style="font-size: 15px;position: absolute;padding: 10px 10px 10px 0;">{note}</span>' |
||||
] |
||||
} |
||||
] |
||||
} |
||||
]; |
||||
|
||||
me.buttons = [ |
||||
{ |
||||
text: 'Cancel' |
||||
,ui: 'decline' |
||||
,handler: 'doCancel' |
||||
} |
||||
,'->' |
||||
,{ |
||||
text: me.title |
||||
,itemId: 'submit' |
||||
,handler: 'doSave' |
||||
} |
||||
]; |
||||
|
||||
this.callParent(this); |
||||
} |
||||
|
||||
,listeners: { |
||||
show: 'onShow' |
||||
} |
||||
}); |
@ -0,0 +1,125 @@
|
||||
Ext.define('Rambox.view.add.AddController', { |
||||
extend: 'Ext.app.ViewController' |
||||
,alias: 'controller.add-add' |
||||
|
||||
,doCancel: function( btn ) { |
||||
var me = this; |
||||
|
||||
me.getView().close(); |
||||
} |
||||
|
||||
,doSave: function( btn ) { |
||||
var me = this; |
||||
|
||||
var win = me.getView(); |
||||
if ( !win.down('form').isValid() ) return false; |
||||
|
||||
var formValues = win.down('form').getValues(); |
||||
|
||||
if ( win.edit ) { |
||||
// Format data
|
||||
if ( win.service.get('url').indexOf('___') >= 0 ) { |
||||
formValues.url = formValues.cycleValue === '1' ? win.service.get('url').replace('___', formValues.url) : formValues.url; |
||||
} |
||||
|
||||
var oldData = win.record.getData(); |
||||
win.record.set({ |
||||
logo: formValues.logo |
||||
,name: formValues.serviceName |
||||
,url: formValues.url |
||||
,align: formValues.align |
||||
,notifications: formValues.notifications |
||||
,muted: formValues.muted |
||||
,trust: formValues.trust |
||||
,js_unread: formValues.js_unread |
||||
}); |
||||
// Change the title of the Tab
|
||||
Ext.getCmp('tab_'+win.record.get('id')).setTitle(formValues.serviceName); |
||||
// Change sound of the Tab
|
||||
Ext.getCmp('tab_'+win.record.get('id')).setAudioMuted(formValues.muted); |
||||
// Change notifications of the Tab
|
||||
Ext.getCmp('tab_'+win.record.get('id')).setNotifications(formValues.notifications); |
||||
// Change the icon of the Tab
|
||||
if ( win.record.get('type') === 'custom' && oldData.logo !== formValues.logo ) Ext.getCmp('tab_'+win.record.get('id')).setConfig('icon', formValues.logo === '' ? 'resources/icons/custom.png' : formValues.logo); |
||||
// Change the URL of the Tab
|
||||
if ( oldData.url !== formValues.url ) Ext.getCmp('tab_'+win.record.get('id')).setURL(formValues.url); |
||||
// Change the align of the Tab
|
||||
if ( oldData.align !== formValues.align ) { |
||||
if ( formValues.align === 'left' ) { |
||||
Ext.cq1('app-main').moveBefore(Ext.getCmp('tab_'+win.record.get('id')), Ext.getCmp('tbfill')); |
||||
} else { |
||||
Ext.cq1('app-main').moveAfter(Ext.getCmp('tab_'+win.record.get('id')), Ext.getCmp('tbfill')); |
||||
} |
||||
} |
||||
// Apply the JS Code of the Tab
|
||||
if ( win.down('textarea').isDirty() ) { |
||||
Ext.Msg.confirm('CUSTOM CODE', 'Rambox needs to reload the service to execute the new JavaScript code. Do you want to do it now?', function( btnId ) { |
||||
if ( btnId === 'yes' ) Ext.getCmp('tab_'+win.record.get('id')).reloadService(); |
||||
}); |
||||
} |
||||
|
||||
Ext.getCmp('tab_'+win.record.get('id')).record = win.record; |
||||
Ext.getCmp('tab_'+win.record.get('id')).tabConfig.service = win.record; |
||||
} else { |
||||
// Format data
|
||||
if ( win.record.get('url').indexOf('___') >= 0 ) { |
||||
formValues.url = formValues.cycleValue === '1' ? win.record.get('url').replace('___', formValues.url) : formValues.url; |
||||
} |
||||
|
||||
var service = Ext.create('Rambox.model.Service', { |
||||
type: win.record.get('id') |
||||
,logo: formValues.logo |
||||
,name: formValues.serviceName |
||||
,url: formValues.url |
||||
,align: formValues.align |
||||
,notifications: formValues.notifications |
||||
,muted: formValues.muted |
||||
,trust: formValues.trust |
||||
,js_unread: formValues.js_unread |
||||
}); |
||||
service.save(); |
||||
Ext.getStore('Services').add(service); |
||||
|
||||
var tabData = { |
||||
xtype: 'webview' |
||||
,id: 'tab_'+service.get('id') |
||||
/* |
||||
,title: service.get('name') |
||||
,icon: service.get('logo') |
||||
,src: service.get('url') |
||||
,type: service.get('type') |
||||
,align: formValues.align |
||||
,notifications: formValues.notifications |
||||
,muted: formValues.muted |
||||
*/ |
||||
,record: service |
||||
,tabConfig: { |
||||
service: service |
||||
} |
||||
}; |
||||
|
||||
if ( formValues.align === 'left' ) { |
||||
var tbfill = Ext.cq1('app-main').getTabBar().down('tbfill'); |
||||
Ext.cq1('app-main').insert(Ext.cq1('app-main').getTabBar().items.indexOf(tbfill), tabData).show(); |
||||
} else { |
||||
Ext.cq1('app-main').add(tabData).show(); |
||||
} |
||||
} |
||||
|
||||
win.close(); |
||||
} |
||||
|
||||
,onEnter: function(field, e) { |
||||
var me = this; |
||||
|
||||
if ( e.getKey() == e.ENTER && field.up('form').isValid() ) me.doSave(); |
||||
} |
||||
|
||||
,onShow: function(win) { |
||||
var me = this; |
||||
|
||||
// Make focus to the name field
|
||||
win.down('textfield[name="serviceName"]').focus(true, 100); |
||||
} |
||||
|
||||
}); |
@ -0,0 +1,4 @@
|
||||
Ext.define('Rambox.view.add.AddModel', { |
||||
extend: 'Ext.app.ViewModel' |
||||
,alias: 'viewmodel.add-add' |
||||
}); |
After Width: | Height: | Size: 7.6 KiB |
@ -0,0 +1,229 @@
|
||||
/* Main component wrapper */ |
||||
body { |
||||
overflow: hidden; |
||||
} |
||||
.component { |
||||
position: absolute;; |
||||
z-index: 1; |
||||
width: 200px; |
||||
height: 200px; |
||||
margin: -100px 0 0 -100px; |
||||
top: 50%; |
||||
left: 50%; |
||||
} |
||||
|
||||
|
||||
/* Actual buttons (laid over shapes) */ |
||||
|
||||
.button { |
||||
font-weight: bold; |
||||
position: absolute; |
||||
bottom: 4px; |
||||
top: 50%; |
||||
left: 50%; |
||||
width: 200px; |
||||
height: 200px; |
||||
margin: -100px 0 0 -100px; |
||||
padding: 0; |
||||
text-align: center; |
||||
color: #00a7e7; |
||||
border: none; |
||||
background: none; |
||||
-webkit-transition: opacity 0.3s; |
||||
transition: opacity 0.3s; |
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); |
||||
} |
||||
|
||||
.button:hover, |
||||
.button:focus { |
||||
outline: none; |
||||
color: #048abd; |
||||
} |
||||
|
||||
.button--listen { |
||||
pointer-events: none; |
||||
} |
||||
|
||||
.button--close { |
||||
z-index: 10; |
||||
top: 0px; |
||||
right: 0px; |
||||
left: auto; |
||||
width: 40px; |
||||
height: 40px; |
||||
padding: 10px; |
||||
color: #fff; |
||||
} |
||||
|
||||
.button--close:hover, |
||||
.button--close:focus { |
||||
color: #ddd; |
||||
} |
||||
|
||||
.button--hidden { |
||||
pointer-events: none; |
||||
opacity: 0; |
||||
} |
||||
|
||||
|
||||
/* Inner content of the start/*/ |
||||
|
||||
.button__content { |
||||
position: absolute; |
||||
opacity: 0; |
||||
-webkit-transition: -webkit-transform 0.4s, opacity 0.4s; |
||||
transition: transform 0.4s, opacity 0.4s; |
||||
} |
||||
|
||||
.button__content--listen { |
||||
font-size: 1.75em; |
||||
line-height: 64px; |
||||
bottom: 0; |
||||
left: 50%; |
||||
width: 60px; |
||||
height: 60px; |
||||
margin: 0 0 0 -30px; |
||||
border-radius: 50%; |
||||
-webkit-transform: translate3d(0, 25px, 0); |
||||
transform: translate3d(0, 25px, 0); |
||||
-webkit-transition-timing-function: cubic-bezier(0.8, 0, 0.2, 1); |
||||
transition-timing-function: cubic-bezier(0.8, 0, 0.2, 1); |
||||
} |
||||
|
||||
.button__content--listen::before, |
||||
.button__content--listen::after { |
||||
content: ''; |
||||
position: absolute; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
pointer-events: none; |
||||
opacity: 0; |
||||
border: 1px solid rgba(255, 255, 255, 0.2); |
||||
border-radius: 50%; |
||||
} |
||||
|
||||
.button--animate .button__content--listen::before, |
||||
.button--animate .button__content--listen::after { |
||||
-webkit-animation: anim-ripple 1.2s ease-out infinite forwards; |
||||
animation: anim-ripple 1.2s ease-out infinite forwards; |
||||
} |
||||
|
||||
.button--animate .button__content--listen::after { |
||||
-webkit-animation-delay: 0.6s; |
||||
animation-delay: 0.6s; |
||||
} |
||||
|
||||
@-webkit-keyframes anim-ripple { |
||||
0% { |
||||
opacity: 0; |
||||
-webkit-transform: scale3d(3, 3, 1); |
||||
transform: scale3d(3, 3, 1); |
||||
} |
||||
50% { |
||||
opacity: 1; |
||||
} |
||||
100% { |
||||
opacity: 0; |
||||
-webkit-transform: scale3d(1, 1, 1); |
||||
transform: scale3d(1, 1, 1); |
||||
} |
||||
} |
||||
|
||||
@keyframes anim-ripple { |
||||
0% { |
||||
opacity: 0; |
||||
-webkit-transform: scale3d(3, 3, 1); |
||||
transform: scale3d(3, 3, 1); |
||||
} |
||||
50% { |
||||
opacity: 1; |
||||
} |
||||
100% { |
||||
opacity: 0; |
||||
-webkit-transform: scale3d(1, 1, 1); |
||||
transform: scale3d(1, 1, 1); |
||||
} |
||||
} |
||||
|
||||
.notes { |
||||
position: absolute; |
||||
z-index: -1; |
||||
bottom: 0; |
||||
left: 50%; |
||||
width: 200px; |
||||
height: 100px; |
||||
margin: 0 0 0 -100px; |
||||
} |
||||
|
||||
.note { |
||||
font-size: 2.8em; |
||||
position: absolute; |
||||
left: 50%; |
||||
width: 1em; |
||||
margin: 0 0 0 -0.5em; |
||||
opacity: 0; |
||||
color: rgba(255, 255, 255, 0.75); |
||||
} |
||||
|
||||
.note:nth-child(odd) { |
||||
color: rgba(0, 0, 0, 0.1); |
||||
} |
||||
|
||||
.note:nth-child(4n) { |
||||
font-size: 2em; |
||||
} |
||||
|
||||
.note:nth-child(6n) { |
||||
color: rgba(255, 255, 255, 0.3); |
||||
} |
||||
|
||||
/* ICONS */ |
||||
@font-face { |
||||
font-family: 'icomoon'; |
||||
src:url('../resources/fonts/icomoon/icomoon.eot?4djz1y'); |
||||
src:url('../resources/fonts/icomoon/icomoon.eot?4djz1y#iefix') format('embedded-opentype'), |
||||
url('../resources/fonts/icomoon/icomoon.ttf?4djz1y') format('truetype'), |
||||
url('../resources/fonts/icomoon/icomoon.woff?4djz1y') format('woff'), |
||||
url('../resources/fonts/icomoon/icomoon.svg?4djz1y#icomoon') format('svg'); |
||||
font-weight: normal; |
||||
font-style: normal; |
||||
} |
||||
|
||||
.icon { |
||||
font-family: 'icomoon'; |
||||
speak: none; |
||||
font-style: normal; |
||||
font-weight: normal; |
||||
font-variant: normal; |
||||
text-transform: none; |
||||
line-height: 1; |
||||
-webkit-font-smoothing: antialiased; |
||||
-moz-osx-font-smoothing: grayscale; |
||||
} |
||||
|
||||
|
||||
.icon--microphone:before { |
||||
content: "\ea95"; |
||||
} |
||||
.icon--cross:before { |
||||
content: "\e90c"; |
||||
} |
||||
.icon--note1:before { |
||||
content: "\ea83"; |
||||
} |
||||
.icon--note2:before { |
||||
content: "\eaad"; |
||||
} |
||||
.icon--note3:before { |
||||
content: "\eac5"; |
||||
} |
||||
.icon--note4:before { |
||||
content: "\ea93"; |
||||
} |
||||
.icon--note5:before { |
||||
content: "\ea95"; |
||||
} |
||||
.icon--note6:before { |
||||
content: "\ea96"; |
||||
} |
@ -0,0 +1,3 @@
|
||||
.x-action-col-glyph { |
||||
color: lighten($base-color, 20%); |
||||
} |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 57 KiB |
@ -0,0 +1,263 @@
|
||||
/*! modernizr 3.2.0 (Custom Build) | MIT * |
||||
* http://modernizr.com/download/?-csstransitions-prefixedcss !*/
|
||||
!function(e,n,t){function r(e,n){return typeof e===n}function o(){var e,n,t,o,i,s,a;for(var f in C)if(C.hasOwnProperty(f)){if(e=[],n=C[f],n.name&&(e.push(n.name.toLowerCase()),n.options&&n.options.aliases&&n.options.aliases.length))for(t=0;t<n.options.aliases.length;t++)e.push(n.options.aliases[t].toLowerCase());for(o=r(n.fn,"function")?n.fn():n.fn,i=0;i<e.length;i++)s=e[i],a=s.split("."),1===a.length?Modernizr[a[0]]=o:(!Modernizr[a[0]]||Modernizr[a[0]]instanceof Boolean||(Modernizr[a[0]]=new Boolean(Modernizr[a[0]])),Modernizr[a[0]][a[1]]=o),g.push((o?"":"no-")+a.join("-"))}}function i(e){var n=_.className,t=Modernizr._config.classPrefix||"";if(w&&(n=n.baseVal),Modernizr._config.enableJSClass){var r=new RegExp("(^|\\s)"+t+"no-js(\\s|$)");n=n.replace(r,"$1"+t+"js$2")}Modernizr._config.enableClasses&&(n+=" "+t+e.join(" "+t),w?_.className.baseVal=n:_.className=n)}function s(e){return e.replace(/([A-Z])/g,function(e,n){return"-"+n.toLowerCase()}).replace(/^ms-/,"-ms-")}function a(e){return e.replace(/([a-z])-([a-z])/g,function(e,n,t){return n+t.toUpperCase()}).replace(/^-/,"")}function f(e,n){return!!~(""+e).indexOf(n)}function l(){return"function"!=typeof n.createElement?n.createElement(arguments[0]):w?n.createElementNS.call(n,"http://www.w3.org/2000/svg",arguments[0]):n.createElement.apply(n,arguments)}function u(e,n){return function(){return e.apply(n,arguments)}}function p(e,n,t){var o;for(var i in e)if(e[i]in n)return t===!1?e[i]:(o=n[e[i]],r(o,"function")?u(o,t||n):o);return!1}function d(){var e=n.body;return e||(e=l(w?"svg":"body"),e.fake=!0),e}function c(e,t,r,o){var i,s,a,f,u="modernizr",p=l("div"),c=d();if(parseInt(r,10))for(;r--;)a=l("div"),a.id=o?o[r]:u+(r+1),p.appendChild(a);return i=l("style"),i.type="text/css",i.id="s"+u,(c.fake?c:p).appendChild(i),c.appendChild(p),i.styleSheet?i.styleSheet.cssText=e:i.appendChild(n.createTextNode(e)),p.id=u,c.fake&&(c.style.background="",c.style.overflow="hidden",f=_.style.overflow,_.style.overflow="hidden",_.appendChild(c)),s=t(p,e),c.fake?(c.parentNode.removeChild(c),_.style.overflow=f,_.offsetHeight):p.parentNode.removeChild(p),!!s}function m(n,r){var o=n.length;if("CSS"in e&&"supports"in e.CSS){for(;o--;)if(e.CSS.supports(s(n[o]),r))return!0;return!1}if("CSSSupportsRule"in e){for(var i=[];o--;)i.push("("+s(n[o])+":"+r+")");return i=i.join(" or "),c("@supports ("+i+") { #modernizr { position: absolute; } }",function(e){return"absolute"==getComputedStyle(e,null).position})}return t}function v(e,n,o,i){function s(){p&&(delete N.style,delete N.modElem)}if(i=r(i,"undefined")?!1:i,!r(o,"undefined")){var u=m(e,o);if(!r(u,"undefined"))return u}for(var p,d,c,v,h,y=["modernizr","tspan"];!N.style;)p=!0,N.modElem=l(y.shift()),N.style=N.modElem.style;for(c=e.length,d=0;c>d;d++)if(v=e[d],h=N.style[v],f(v,"-")&&(v=a(v)),N.style[v]!==t){if(i||r(o,"undefined"))return s(),"pfx"==n?v:!0;try{N.style[v]=o}catch(g){}if(N.style[v]!=h)return s(),"pfx"==n?v:!0}return s(),!1}function h(e,n,t,o,i){var s=e.charAt(0).toUpperCase()+e.slice(1),a=(e+" "+b.join(s+" ")+s).split(" ");return r(n,"string")||r(n,"undefined")?v(a,n,o,i):(a=(e+" "+P.join(s+" ")+s).split(" "),p(a,n,t))}function y(e,n,r){return h(e,t,t,n,r)}var g=[],C=[],x={_version:"3.2.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,n){var t=this;setTimeout(function(){n(t[e])},0)},addTest:function(e,n,t){C.push({name:e,fn:n,options:t})},addAsyncTest:function(e){C.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=x,Modernizr=new Modernizr;var _=n.documentElement,w="svg"===_.nodeName.toLowerCase(),S="Moz O ms Webkit",b=x._config.usePrefixes?S.split(" "):[];x._cssomPrefixes=b;var E=function(n){var r,o=prefixes.length,i=e.CSSRule;if("undefined"==typeof i)return t;if(!n)return!1;if(n=n.replace(/^@/,""),r=n.replace(/-/g,"_").toUpperCase()+"_RULE",r in i)return"@"+n;for(var s=0;o>s;s++){var a=prefixes[s],f=a.toUpperCase()+"_"+r;if(f in i)return"@-"+a.toLowerCase()+"-"+n}return!1};x.atRule=E;var P=x._config.usePrefixes?S.toLowerCase().split(" "):[];x._domPrefixes=P;var z={elem:l("modernizr")};Modernizr._q.push(function(){delete z.elem});var N={style:z.elem.style};Modernizr._q.unshift(function(){delete N.style}),x.testAllProps=h;var T=x.prefixed=function(e,n,t){return 0===e.indexOf("@")?E(e):(-1!=e.indexOf("-")&&(e=a(e)),n?h(e,n,t):h(e,"pfx"))};x.prefixedCSS=function(e){var n=T(e);return n&&s(n)};x.testAllProps=y,Modernizr.addTest("csstransitions",y("transition","all",!0)),o(),i(g),delete x.addTest,delete x.addAsyncTest;for(var j=0;j<Modernizr._q.length;j++)Modernizr._q[j]();e.Modernizr=Modernizr}(window,document); |
||||
|
||||
/** |
||||
* main.js |
||||
* http://www.codrops.com
|
||||
* |
||||
* Licensed under the MIT license. |
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* |
||||
* Copyright 2015, Codrops |
||||
* http://www.codrops.com
|
||||
*/ |
||||
;(function(window) { |
||||
|
||||
'use strict'; |
||||
|
||||
/** |
||||
* some helper functions |
||||
*/ |
||||
|
||||
// from http://stackoverflow.com/a/25273333
|
||||
var bezier = function(x1, y1, x2, y2, epsilon) { |
||||
var curveX = function(t){ |
||||
var v = 1 - t; |
||||
return 3 * v * v * t * x1 + 3 * v * t * t * x2 + t * t * t; |
||||
}; |
||||
var curveY = function(t){ |
||||
var v = 1 - t; |
||||
return 3 * v * v * t * y1 + 3 * v * t * t * y2 + t * t * t; |
||||
}; |
||||
var derivativeCurveX = function(t){ |
||||
var v = 1 - t; |
||||
return 3 * (2 * (t - 1) * t + v * v) * x1 + 3 * (- t * t * t + 2 * v * t) * x2; |
||||
}; |
||||
return function(t){ |
||||
var x = t, t0, t1, t2, x2, d2, i; |
||||
// First try a few iterations of Newton's method -- normally very fast.
|
||||
for (t2 = x, i = 0; i < 8; i++){ |
||||
x2 = curveX(t2) - x; |
||||
if (Math.abs(x2) < epsilon) return curveY(t2); |
||||
d2 = derivativeCurveX(t2); |
||||
if (Math.abs(d2) < 1e-6) break; |
||||
t2 = t2 - x2 / d2; |
||||
} |
||||
|
||||
t0 = 0, t1 = 1, t2 = x; |
||||
|
||||
if (t2 < t0) return curveY(t0); |
||||
if (t2 > t1) return curveY(t1); |
||||
|
||||
// Fallback to the bisection method for reliability.
|
||||
while (t0 < t1){ |
||||
x2 = curveX(t2); |
||||
if (Math.abs(x2 - x) < epsilon) return curveY(t2); |
||||
if (x > x2) t0 = t2; |
||||
else t1 = t2; |
||||
t2 = (t1 - t0) * .5 + t0; |
||||
} |
||||
// Failure
|
||||
return curveY(t2); |
||||
}; |
||||
}, |
||||
getRandomNumber = function(min, max) { |
||||
return Math.floor(Math.random() * (max - min + 1)) + min; |
||||
}, |
||||
throttle = function(fn, delay) { |
||||
var allowSample = true; |
||||
|
||||
return function(e) { |
||||
if (allowSample) { |
||||
allowSample = false; |
||||
setTimeout(function() { allowSample = true; }, delay); |
||||
fn(e); |
||||
} |
||||
}; |
||||
}, |
||||
// from https://davidwalsh.name/vendor-prefix
|
||||
prefix = (function () { |
||||
var styles = window.getComputedStyle(document.documentElement, ''), |
||||
pre = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o']))[1], |
||||
dom = ('WebKit|Moz|MS|O').match(new RegExp('(' + pre + ')', 'i'))[1]; |
||||
|
||||
return { |
||||
dom: dom, |
||||
lowercase: pre, |
||||
css: '-' + pre + '-', |
||||
js: pre[0].toUpperCase() + pre.substr(1) |
||||
}; |
||||
})(); |
||||
|
||||
var support = {transitions : Modernizr.csstransitions}, |
||||
transEndEventNames = { 'WebkitTransition': 'webkitTransitionEnd', 'MozTransition': 'transitionend', 'OTransition': 'oTransitionEnd', 'msTransition': 'MSTransitionEnd', 'transition': 'transitionend' }, |
||||
transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ], |
||||
onEndTransition = function( el, callback, propTest ) { |
||||
var onEndCallbackFn = function( ev ) { |
||||
if( support.transitions ) { |
||||
if( ev.target != this || propTest && ev.propertyName !== propTest && ev.propertyName !== prefix.css + propTest ) return; |
||||
this.removeEventListener( transEndEventName, onEndCallbackFn ); |
||||
} |
||||
if( callback && typeof callback === 'function' ) { callback.call(this); } |
||||
}; |
||||
if( support.transitions ) { |
||||
el.addEventListener( transEndEventName, onEndCallbackFn ); |
||||
} |
||||
else { |
||||
onEndCallbackFn(); |
||||
} |
||||
}, |
||||
// the main component element/wrapper
|
||||
shzEl = document.querySelector('.component'), |
||||
// the initial button
|
||||
shzCtrl = shzEl.querySelector('div.button--start'), |
||||
// total number of notes/symbols moving towards the listen button
|
||||
totalNotes = 50, |
||||
// the notes elements
|
||||
notes, |
||||
// the note´s speed factor relative to the distance from the note element to the button.
|
||||
// if notesSpeedFactor = 1, then the speed equals the distance (in ms)
|
||||
notesSpeedFactor = 4.5, |
||||
// window sizes
|
||||
winsize = {width: window.innerWidth, height: window.innerHeight}, |
||||
// button offset
|
||||
shzCtrlOffset = shzCtrl.getBoundingClientRect(), |
||||
// button sizes
|
||||
shzCtrlSize = {width: shzCtrl.offsetWidth, height: shzCtrl.offsetHeight}, |
||||
// tells us if the listening animation is taking place
|
||||
isListening = false, |
||||
// audio player element
|
||||
playerEl = shzEl.querySelector('.player'); |
||||
// close player control
|
||||
//playerCloseCtrl = playerEl.querySelector('.button--close');
|
||||
|
||||
function init() { |
||||
// create the music notes elements - the musical symbols that will animate/move towards the listen button
|
||||
createNotes(); |
||||
// star animation
|
||||
listen(); |
||||
} |
||||
|
||||
/** |
||||
* creates [totalNotes] note elements (the musical symbols that will animate/move towards the listen button) |
||||
*/ |
||||
function createNotes() { |
||||
var notesEl = document.createElement('div'), notesElContent = ''; |
||||
notesEl.className = 'notes'; |
||||
for(var i = 0; i < totalNotes; ++i) { |
||||
// we have 6 different types of symbols (icon--note1, icon--note2 ... icon--note6)
|
||||
var j = (i + 1) - 6 * Math.floor(i/6); |
||||
notesElContent += '<div class="note icon icon--note' + j + '"></div>'; |
||||
} |
||||
notesEl.innerHTML = notesElContent; |
||||
shzEl.insertBefore(notesEl, shzEl.firstChild) |
||||
|
||||
// reference to the notes elements
|
||||
notes = [].slice.call(notesEl.querySelectorAll('.note')); |
||||
} |
||||
|
||||
/** |
||||
* transform the initial button into a circle shaped one that "listens" to the current song.. |
||||
*/ |
||||
function listen() { |
||||
isListening = true; |
||||
|
||||
showNotes(); |
||||
} |
||||
|
||||
/** |
||||
* stop the ripples and notes animations |
||||
*/ |
||||
function stopListening() { |
||||
isListening = false; |
||||
// music notes animation stops...
|
||||
hideNotes(); |
||||
} |
||||
|
||||
/** |
||||
* show the notes elements: first set a random position and then animate them towards the button |
||||
*/ |
||||
function showNotes() { |
||||
notes.forEach(function(note) { |
||||
// first position the notes randomly on the page
|
||||
positionNote(note); |
||||
// now, animate the notes torwards the button
|
||||
animateNote(note); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* fade out the notes elements |
||||
*/ |
||||
function hideNotes() { |
||||
notes.forEach(function(note) { |
||||
note.style.opacity = 0; |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* positions a note/symbol randomly on the page. The area is restricted to be somewhere outside of the viewport. |
||||
* @param {Element Node} note - the note element |
||||
*/ |
||||
function positionNote(note) { |
||||
// we want to position the notes randomly (translation and rotation) outside of the viewport
|
||||
var x = getRandomNumber(-2*(shzCtrlOffset.left + shzCtrlSize.width/2), 2*(winsize.width - (shzCtrlOffset.left + shzCtrlSize.width/2))), y, |
||||
rotation = getRandomNumber(-30, 30); |
||||
|
||||
if( x > -1*(shzCtrlOffset.top + shzCtrlSize.height/2) && x < shzCtrlOffset.top + shzCtrlSize.height/2 ) { |
||||
y = getRandomNumber(0,1) > 0 ? getRandomNumber(-2*(shzCtrlOffset.top + shzCtrlSize.height/2), -1*(shzCtrlOffset.top + shzCtrlSize.height/2)) : getRandomNumber(winsize.height - (shzCtrlOffset.top + shzCtrlSize.height/2), winsize.height + winsize.height - (shzCtrlOffset.top + shzCtrlSize.height/2)); |
||||
} |
||||
else { |
||||
y = getRandomNumber(-2*(shzCtrlOffset.top + shzCtrlSize.height/2), winsize.height + winsize.height - (shzCtrlOffset.top + shzCtrlSize.height/2)); |
||||
} |
||||
|
||||
// first reset transition if any
|
||||
note.style.WebkitTransition = note.style.transition = 'none'; |
||||
|
||||
// apply the random transforms
|
||||
note.style.WebkitTransform = note.style.transform = 'translate3d(' + x + 'px,' + y + 'px,0) rotate3d(0,0,1,' + rotation + 'deg)'; |
||||
|
||||
// save the translation values for later
|
||||
note.setAttribute('data-tx', Math.abs(x)); |
||||
note.setAttribute('data-ty', Math.abs(y)); |
||||
} |
||||
|
||||
/** |
||||
* animates a note torwards the button. Once that's done, it repositions the note and animates it again until the component is no longer listening. |
||||
* @param {Element Node} note - the note element |
||||
*/ |
||||
function animateNote(note) { |
||||
setTimeout(function() { |
||||
if(!isListening) return; |
||||
// the transition speed of each note will be proportional to the its distance to the button
|
||||
// speed = notesSpeedFactor * distance
|
||||
var noteSpeed = notesSpeedFactor * Math.sqrt(Math.pow(note.getAttribute('data-tx'),2) + Math.pow(note.getAttribute('data-ty'),2)); |
||||
|
||||
// apply the transition
|
||||
note.style.WebkitTransition = '-webkit-transform ' + noteSpeed + 'ms ease, opacity 0.8s'; |
||||
note.style.transition = 'transform ' + noteSpeed + 'ms ease-in, opacity 0.8s'; |
||||
|
||||
// now apply the transform (reset the transform so the note moves to its original position) and fade in the note
|
||||
note.style.WebkitTransform = note.style.transform = 'translate3d(0,0,0)'; |
||||
note.style.opacity = 1; |
||||
|
||||
// after the animation is finished,
|
||||
var onEndTransitionCallback = function() { |
||||
// reset transitions and styles
|
||||
note.style.WebkitTransition = note.style.transition = 'none'; |
||||
note.style.opacity = 0; |
||||
|
||||
if(!isListening) return; |
||||
|
||||
positionNote(note); |
||||
animateNote(note); |
||||
}; |
||||
|
||||
onEndTransition(note, onEndTransitionCallback, 'transform'); |
||||
}, 60); |
||||
} |
||||
|
||||
init(); |
||||
|
||||
})(window); |