diff --git a/WiFi_profile/assets/fonts/Inconsolata.woff2 b/WiFi_profile/assets/fonts/Inconsolata.woff2
new file mode 100644
index 00000000..e2514070
Binary files /dev/null and b/WiFi_profile/assets/fonts/Inconsolata.woff2 differ
diff --git a/WiFi_profile/assets/js/common.js b/WiFi_profile/assets/js/common.js
index d134fa88..ad971013 100644
--- a/WiFi_profile/assets/js/common.js
+++ b/WiFi_profile/assets/js/common.js
@@ -1,277 +1,16 @@
-/*
-bash()
-$.fn.press
-banner() copy errorDisplay()
-info() infoPower() infoPowerCommand() infoWarning()
-loader() local() selectSet()
-*/
-
-var page = location.search.replace( '?p=', '' );
-var dirbash = '/srv/http/bash/';
-var dirsettings = '/srv/http/bash/settings/';
-var iconwarning = ico( 'warning i-22 yl' ) +' ';
-var localhost = [ 'localhost', '127.0.0.1' ].includes( location.hostname );
-var orange = '#de810e';
-var red = '#bb2828';
-var blinkdot = '· · ·';
-
-// ----------------------------------------------------------------------
-/*
-$( ELEMENT ).press( DELEGATE, function( e ) {
- - this not applicable
- - cannot be attached with .on
- - DELEGATE : optional
-} );
-events:
- - move : mouseenter > mousemove > mouseleave > mouseout
- - click : mousedown > mouseup > click
- - touch : touchstart > touchmove > touchend
-*/
-$.fn.press = function( arg1, arg2 ) {
- var callback, delegate, timeout;
- if ( arg2 ) {
- delegate = arg1;
- callback = arg2;
- } else {
- delegate = '';
- callback = arg1;
- }
- this.on( 'touchstart mousedown', delegate, function( e ) {
- timeout = setTimeout( () => {
- V.press = true;
- callback( e ); // e.currentTarget = ELEMENT
- }, 1000 );
- } ).on( 'touchend mouseup mouseleave', delegate, function() {
- clearTimeout( timeout );
- setTimeout( () => V.press = false, 300 ); // needed for mouse events
- } );
- return this // allow chain
-}
-
-// ----------------------------------------------------------------------
-/*
-Simple spaced arguments
- - [ 'CMD.sh', v1, v2, ... ] - CMD.sh $1 $2 ...
-Multiline arguments - no escape \" \` in js values > escape in php instead
- - [ CMD, v1, v2, ... ] - script.sh $CMD ON=1 "${args[1]}" "${args[2]}" ...
- - [ CMD, 'OFF' ] - script.sh $CMD ON= (disable CMD)
- - [ CMD, v1, v2, ..., 'CMD K1 K2 ...' ] - script.sh $CMD ON=1 "$K1" "$K2" ...
- - [ CMD, v1, v2, ..., 'CFG K1 K2 ...' ] - ^^^ and save K1=v1; K2=v2; ... to $dirsystem/$CMD.conf
- - { cmd: [ CMD, ... ], json: JSON } - ^^^ and save {"K1":"v1", ... } to $dirsystem/$CMD.json
-
-- js > php >> common.js - bash()
- - string :
- - array of lines : [ 'CMD' v1, v2, ..., 'CMD K1 K2 ...' ]
- - multiline : 'l1\\nl2\\nl3...'
- - json : json.sringify( JSON )
-- php > bash >> cmd.php - $_POST[ 'cmd' ] === 'bash'
- - array : covert to multiline with " ` escaped > CMD "...\"...\n...\`..."
- - json : decode > reencode > save to $dirsystem/$CMD.json ($_POST[ 'json' ])
- - js cannot escape " as \\" double backslash which disappeared in bash
-- bash >> common.sh - args2var
- - convert to array > assign values
- - No 'CMD' : ${args[1]} == v1; ${args[2]} == v2; ...
- - With 'CMD' : $K1 == v1; $K2 == v2; ... ($VAR in capital)
- - With 'CFG' :
- - the same as 'CMD'
- - save to $dirsystem/$CMD.conf with " ` escaped and quote > K1="... ...\"...\n...\`..."
-*/
-function bash( args, callback, json ) {
- var data = { cmd: 'bash' }
- if ( 'json' in args ) {
- data.json = JSON.stringify( args.json );
- args = args.cmd;
- }
- var args0 = args[ 0 ];
- if ( [ '.sh', '.py' ].includes( args0.slice( -3 ) ) ) { // CMD.sh / CMD.py
- data.filesh = args.join( ' ' );
- args = false;
- } else if ( page ) { // CMD - settings
- data.filesh = 'settings/'+ page +'.sh'; // default
- if ( args0 === 'mount' ) data.filesh = 'settings/system-mount.sh'; // not default
- } else { // CMD - playback
- data.filesh = 'cmd.sh';
- if ( [ 'scrobble', 'tageditor' ].includes( args0 ) ) data.filesh = args0 +'.sh';
- }
- if ( args ) data.args = args;
-/*
-V.debug - press: $( '#debug' )
- - all
- - console.log commands
- - active push status (no pageInactive)
-V.consolelog - press: $( '#infoOk' ) / $( '.switch' )
- - each
- - console.log commands only (NOT run)
-*/
- if ( V.debug || V.consoleonly ) {
- var bashcmd = data.filesh.replace( 'settings/', '' );
- if ( data.args ) bashcmd += ' "\\\n'+ data.args.join( '\n' ).replace( /"/g, '\\"' ) +'"';
- console.log( data );
- console.log( bashcmd );
- if ( V.consoleonly ) {
- V.consoleonly = false;
- setTimeout( () => page ? switchCancel() : bannerHide(), 5000 );
- return
- }
- }
-
- $.post(
- 'cmd.php'
- , data
- , callback || null
- , json || null
- );
-}
-// debug
-$( '.page-icon' ).press( () => location.reload() );
-$( '#debug' ).press( function() {
- V.debug = true;
- banner( 'gear', 'Debug', 'Console.log + Push status', 5000 );
- bash( [ 'cmd.sh', 'cachebust' ] );
-} );
-$( '#infoOverlay' ).press( '#infoOk', function() {
- V.consoleonly = true;
- I.ok();
-} );
-$( '.col-r .switch' ).press( function( e ) {
- if ( $( '#setting-'+ e.target.id ).length && ! S[ e.target.id ] ) {
- $( '#setting-'+ e.target.id ).trigger( 'click' );
- return
- }
-
- V.consoleonly = true;
- switchIdIconTitle( e.target.id );
- notifyCommon( S[ SW.id ] ? 'Disable ...' : 'Enable ...' );
- bash( S[ SW.id ] ? [ SW.id, 'OFF' ] : [ SW.id ] );
-} );
-
-// ----------------------------------------------------------------------
-function banner( icon, title, message, delay ) {
- clearTimeout( I.timeoutbanner );
- var bottom = $( '#bar-bottom' ).is( '.transparent, :hidden' ) || ! $( '#loader' ).hasClass( 'hide' ) ? '10px' : '';
- $( '#banner' )
- .html( '
'
- + list.slice( 0, pos ).replace( /<'+ list.slice( pos ).replace( /'
- $( '#data' )
- .html( error )
- .removeClass( 'hide' );
- $( '#button-data' ).addClass( 'hide' );
- loaderHide();
-}
-
-// ----------------------------------------------------------------------
-function highlightJSON( json ) {
- var json = Object.keys( json )
- .sort()
- .reduce( ( r, k ) => ( r[ k ] = json[ k ], r ), {} ); // https://stackoverflow.com/a/29622653
- json = JSON.stringify( json, null, '\t' )
- .replace( /'+ match +''
- }
- } else if ( /true/.test( match ) ) { // true
- return '
'+ match +''
- } else if ( /false/.test( match ) ) { // false
- return '
'+ match +''
- } else if ( /[0-9]/.test( match ) ) { // number
- return '
'+ match +''
- } else if ( /[{}\[\]]/.test( match ) ) { // braces
- return '
'+ match +''
- }
- } );
- return '\n\n'+ json.replace( /: null,/g, ':
null,' );
-}
+// info ----------------------------------------------------------------------
function ico( cls, id ) {
return '
'
}
+function local( delay ) {
+ V.local = true;
+ setTimeout( () => V.local = false, delay || 300 );
+}
-// info ----------------------------------------------------------------------
-$( '#infoOverlay' ).press( '#infoIcon', function() { // usage
- window.open( 'https://github.com/rern/js/blob/master/info/README.md#infojs', '_blank' );
-} );
-$( '#infoOverlay' ).on( 'click', '#infoList', function() {
- $( '.infobtn, .filebtn' ).removeClass( 'active' );
-} );
-$( '#infoOverlay' ).on( 'keydown', function( e ) {
-/*
-all: [Tab] - focus / next input
- [Shift+Tab] - previous input
-radio: [L] [R] - check
-checkbox: [space] - check
-select: [U] [D] - check
-*/
- if ( ! I.active ) return
-
- e.stopPropagation(); // suppress others
- var key = e.key;
- switch ( key ) {
- case 'Enter':
- if ( ! $( '#infoOk' ).hasClass( 'disabled' ) && ! $( 'textarea' ).is( ':focus' ) ) $( '#infoOk' ).trigger( 'click' );
- break;
- case 'Escape':
- $( '#infoX' ).trigger( 'click' );
- break;
- case 'ArrowLeft':
- case 'ArrowRight':
- var activeinput = $( document.activeElement ).attr( 'type' );
- if ( [ 'text', 'number', 'password', 'range', 'textarea' ].includes( activeinput ) ) return
-
- var $tabactive = $( '#infoTab a.active' );
- if ( key === 'ArrowLeft' ) {
- $tabactive.is(':first-child') ? $( '#infoTab a:last-child' ).trigger( 'click' ) : $tabactive.prev().trigger( 'click' );
- } else {
- $tabactive.is(':last-child') ? $( '#infoTab a:first-child' ).trigger( 'click' ) : $tabactive.next().trigger( 'click' );
- }
- break;
- }
-} );
-
I = { active: false }
function info( json ) {
- local(); // flag for consecutive info
+ local();
I = json;
if ( 'keyvalue' in I ) $.each( I.keyvalue, ( k, v ) => I[ k ] = v );
if ( 'values' in I ) {
@@ -575,10 +314,6 @@ function info( json ) {
I.active = true;
'focus' in I ? $inputbox.eq( I.focus ).focus() : $( '#infoOverlay' ).focus();
if ( $( '#infoBox' ).height() > window.innerHeight - 10 ) $( '#infoBox' ).css( { top: '5px', transform: 'translateY( 0 )' } );
- infoButtonWidth();
- // set width: text / password / textarea
- infoWidth();
- if ( [ 'localhost', '127.0.0.1' ].includes( location.hostname ) ) $( '#infoList a' ).removeAttr( 'href' );
// check inputs: blank / length / change
if ( I.checkblank ) {
if ( I.checkblank === true ) I.checkblank = [ ...Array( $inputbox.length ).keys() ];
@@ -597,73 +332,6 @@ function info( json ) {
I.nochange = I.values && I.checkchanged ? true : false;
$( '#infoOk' ).toggleClass( 'disabled', I.blank || I.notip || I.short || I.nochange ); // initial check
infoCheckSet();
- if ( I.range ) {
- var timeout, val;
- $( '.inforange input' ).on( 'input', function() {
- var $this = $( this );
- $this.siblings( '.value' ).text( +$this.val() );
- } );
- var rangeset = ( $range, up ) => {
- val = +$range.val();
- up ? val++ : val--;
- $range
- .val( val )
- .siblings( '.value' ).text( val );
- }
- $( '.inforange i' ).on( 'touchend mouseup keyup', function() { // increment up/dn
- clearTimeout( timeout );
- var $this = $( this );
- if ( ! V.press ) rangeset( $this.siblings( 'input' ), $this.hasClass( 'up' ) );
- } ).press( function( e ) {
- var $this = $( e.target );
- var $range = $this.siblings( 'input' )
- var up = $this.hasClass( 'up' );
- timeout = setInterval( () => rangeset( $range, up ), 100 );
- } );
- }
- if ( I.updn.length ) {
- I.updn.forEach( ( el, i ) => {
- var $td = $( '#infoList .updn' ).parent().eq( i );
- var $updn = $td.find( '.updn' );
- var $num = $td.prev().find( 'input' );
- var step = el.step;
- var v = 0;
- var interval, timeout;
- function numberset( up ) {
- v = +$num.val();
- v = up ? v + step : v - step;
- if ( v === el.min || v === el.max ) {
- clearInterval( interval );
- clearTimeout( timeout );
- }
- $num.val( v );
- if ( I.checkchanged ) $num.trigger( 'input' );
- updnToggle( v );
- }
- function updnToggle( v ) {
- $updn.eq( 0 ).toggleClass( 'disabled', v === el.min );
- $updn.eq( 1 ).toggleClass( 'disabled', v === el.max );
- }
- updnToggle( +$num.val() );
- $updn.on( 'click', function() {
- if ( ! V.press ) numberset( $( this ).hasClass( 'up' ) );
- } ).press( function( e ) {
- var up = $( e.target ).hasClass( 'up' );
- interval = setInterval( () => numberset( up ), 100 );
- timeout = setTimeout( () => { // @5 after 3s
- clearInterval( interval );
- step *= 5;
- v = v > 0 ? v + ( step - v % step ) : v - ( step + v % step );
- $num.val( v );
- interval = setInterval( () => numberset( up ), 100 );
- }, 3000 );
- } ).on( 'touchend mouseup keyup', function() {
- clearInterval( interval );
- clearTimeout( timeout );
- step = el.step;
- } );
- } );
- }
// custom function before show
if ( I.beforeshow ) I.beforeshow();
} );
@@ -954,179 +622,3 @@ function infoVal( array ) {
I.keys.forEach( ( k, i ) => v[ k ] = values[ i ] );
return v // json
}
-function infoWarning( icon, title, message ) {
- info( {
- icon : icon
- , title : title
- , message : iconwarning + message
- } );
-}
-function infoWidth() {
- if ( I.boxwidth ) {
- var widthmax = I.boxwidth === 'max';
- if ( widthmax ) {
- if ( I.width ) {
- var maxW = I.width < V.wW ? I.width : V.wW;
- } else {
- var maxW = V.wW > 600 ? 600 : V.wW;
- }
- $( '#infoBox' ).css( 'width', maxW +'px' );
- }
- var allW = $( '#infoList' ).width();
- var labelW = Math.round( $( '#infoList td:first-child' ).width() ) || 0;
- var boxW = ( widthmax ? allW - labelW - 20 : I.boxwidth );
- } else {
- var boxW = 230;
- }
- $( '#infoList table' ).find( 'input:text, input[type=number], input:password, textarea' ).parent().css( 'width', boxW );
- if ( $( '#infoList select' ).length ) {
- selectSet(); // render select to set width
- $( '#infoList .select2-container' ).attr( 'style', 'width: '+ boxW +'px !important' );
- }
- if ( I.headeralign || I.messagealign || I.footeralign ) {
- $( '#infoList' ).find( '.infoheader, .infomessage, .infofooter' ).css( 'width', $( '#infoList table' ).width() );
- }
- if ( I.checkboxonly ) $( '#infoList td' ).css( 'text-align', 'left' );
-}
-
-// common info functions --------------------------------------------------
-function infoPower() {
- info( {
- icon : 'power'
- , title : 'Power'
- , message : ico( 'raudio i-30 gr' ) +' r A u d i o'
- , buttonlabel : ico( 'reboot' ) +'Reboot'
- , buttoncolor : orange
- , button : () => infoPowerCommand( 'reboot' )
- , oklabel : ico( 'power' ) +'Off'
- , okcolor : red
- , ok : () => infoPowerCommand( 'off' )
- } );
-}
-function infoPowerCommand( action ) {
- loader();
- bash( [ 'power.sh', action ], nfs => {
- if ( nfs != -1 ) return
-
- loaderHide();
- var off = action === 'off';
- info( {
- icon : 'power'
- , title : 'Power'
- , message : 'This
Server rAudio '+ ico( 'rserver' ) +' is currently active.'
- +'
Shared Data on clients will stop.'
- +'
(Resume when server online again)'
- +'
Continue?'
- , oklabel : off ? ico( 'power' ) +'Off' : ico( 'reboot' ) +'Reboot'
- , okcolor : off ? red : orange
- , ok : () => {
- bash( [ 'power.sh', action, 'confirm' ] );
- banner( 'rserver', 'Server rAudio', 'Notify clients ...', -1 );
- }
- } );
- } );
-}
-
-function capitalize( str ) {
- return str.replace( /\b\w/g, l => l.toUpperCase() );
-}
-function htmlOption( el ) {
- if ( typeof el === 'number' ) el = [ ...Array( el ).keys() ];
- var options = '';
- if ( Array.isArray( el ) ) { // name = value
- el.sort( ( a, b ) => a.toString().localeCompare( b.toString(), 'en', { numeric: true } ) );
- el.forEach( v => options += '
' );
- } else { // json
- el = jsonSort( el );
- $.each( el, ( k, v ) => options += '
' );
- }
- return options
-}
-function jsonChanged( a, b ) {
- if ( ! a || ! b || ! Object.keys( a ).length || ! Object.keys( b ).length ) return true
-
- var changed = false;
- $.each( a, ( k, v ) => {
- if ( typeof v === 'object' ) {
- if ( jsonChanged( v, b[ k ] ) ) {
- changed = true;
- return false
- }
- } else {
- if ( v !== b[ k ] ) {
- changed = true;
- return false
- }
- }
- } );
- return changed
-}
-function jsonClone( json ) {
- return JSON.parse( JSON.stringify( json ) )
-}
-function jsonSort( json ) {
- return Object.keys( json ).sort().reduce( function ( result, key ) {
- result[ key ] = json[ key ];
- return result;
- }, {} );
-}
-// ----------------------------------------------------------------------
-function loader() {
- $( '#loader' ).removeClass( 'hide' );
-}
-function loaderHide() {
- $( '#loader' ).addClass( 'hide' );
-}
-
-// ----------------------------------------------------------------------
-function local( delay ) {
- V.local = true;
- setTimeout( () => V.local = false, delay || 300 );
-}
-function qrCode( msg ) {
- var qr = QRCode( {
- msg : msg
- , dim : 115
- , pad : 0
- , pal : [ '#969a9c' ]
- } );
- return qr.outerHTML
-}
-
-// select2 --------------------------------------------------------------------
-function selectSet( $select ) {
- var options = { minimumResultsForSearch: 10 }
- if ( ! $select ) {
- $select = $( '#infoList select' );
- if ( $( '#eq' ).length ) options.dropdownParent = $( '#eq' );
- }
- $select
- .select2( options )
- .on( 'select2:open', () => { // fix: scroll on info - set current value 3rd from top
- local(); // fix: onblur / onpagehide
- setTimeout( () => {
- var scroll = $( '.select2-results__option--selected' ).index() * 36 - 72;
- if ( ! navigator.maxTouchPoints ) scroll -= 12;
- $( '.select2-results ul' ).scrollTop( scroll );
- }, 0 );
- } )
- .on( 'select2:closing', local ) // fix: onblur / onpagehide
- .each( ( i, el ) => {
- var $this = $( el );
- $this.prop( 'disabled', $this.find( 'option' ).length === 1 );
- } );
-}
-function selectText2Html( pattern ) {
- function htmlSet( $el ) {
- $.each( pattern, ( k, v ) => {
- if ( $el.text() === k ) $el.html( v );
- } );
- }
- var $rendered = $( '.select2-selection__rendered' ).eq( 0 );
- htmlSet( $rendered );
- $( '#infoList select' ).on( 'select2:open', () => {
- setTimeout( () => $( '.select2-results__options li' ).each( ( i, el ) => htmlSet( $( el ) ) ), 0 );
- } ).on( 'select2:select', function() {
- htmlSet( $rendered );
- } );
-}
diff --git a/WiFi_profile/index.html b/WiFi_profile/index.html
index b284dc87..950325ba 100644
--- a/WiFi_profile/index.html
+++ b/WiFi_profile/index.html
@@ -18,6 +18,10 @@
@@ -29,7 +33,7 @@
-
+