2024-04-23 02:36:54 +03:00
const NeomojiMixer = ( function ( NeomojiMixer ) {
//global variables
2024-04-23 05:25:13 +03:00
const color _names = [
"blue" ,
"lightgrey" ,
"orange" ,
"red" ,
"white" ,
"yellow" ,
2024-04-23 23:45:48 +03:00
"lightbrown" ,
2024-04-23 05:25:13 +03:00
] ;
let selected _color = "blue" ;
let color _change _callbacks = [ ] ;
2024-04-23 02:36:54 +03:00
//shotnames for HTML elements to interact with
const canvas = document . getElementById ( "canvas_export" ) ;
const export _img = document . getElementById ( "imageExport" ) ;
const neomoji _name = document . getElementById ( "fullNeomojiName" ) ;
//Stats
const stats = document . getElementById ( "stats" ) ;
2024-04-23 05:25:13 +03:00
function onColorChange ( ) {
for ( let i = 0 ; i < color _change _callbacks . length ; i ++ ) {
if ( color _change _callbacks [ i ] ) {
color _change _callbacks [ i ] ( ) ;
}
}
}
function PartHandler ( name ) {
this . name = name ;
this . entries = [ ] ; //Arrays to hold the parts
this . entry _indices = [ ] ; //Maps selected_index to entries index
this . selected _index = 0 ; //index_color -> arms.selected_index; index_arms -> arms.entry_indices[arms.selected_index]
this . image _element = document . getElementById ( name + "_img" ) ;
this . name _element = document . getElementById ( name + "_name" ) ;
this . button _left = document . getElementById ( name + "_left" ) ;
this . button _right = document . getElementById ( name + "_right" ) ;
}
PartHandler . prototype = {
fillArray : function ( item ) {
let name = item . name ;
let url = item . url ;
this . entries . push ( [ name , url ] ) ; //Two dimensional array, Second dimension holds name on index 0 and url at index 1
} ,
fillIndices : function ( ) {
for ( let i = 0 ; i < this . entries . length ; i ++ ) {
this . entry _indices . push ( i ) ; //By default preserve index
}
} ,
getSelectedEntry : function ( ) {
return this . entries [ this . entry _indices [ this . selected _index ] ] ;
} ,
setIndex : function ( index ) {
const modulo = this . entry _indices . length ; //Check if index is too big for the array
if ( ! modulo ) {
this . selected _index = 0 ; //Error
} else {
index %= modulo ;
if ( index < 0 ) {
index += modulo ;
}
this . selected _index = index ;
}
this . redraw ( ) ;
} ,
redraw : function ( ) {
const entry = this . getSelectedEntry ( ) ;
this . image _element . src = "." + entry [ 1 ] ; //Change URL of picture
2024-04-23 09:48:38 +03:00
//Change name in controls
this . updateOptions ( ) ;
this . name _element . selectedIndex = this . selected _index ;
2024-04-23 05:25:13 +03:00
} ,
onClickNext : function ( ) {
this . setIndex ( this . selected _index + 1 ) ;
} ,
onClickPrev : function ( ) {
this . setIndex ( this . selected _index - 1 ) ;
} ,
2024-04-23 09:48:38 +03:00
onChangeDropdown : function ( ) {
this . setIndex ( this . name _element . selectedIndex ) ;
} ,
2024-04-23 05:25:13 +03:00
activateControls : function ( ) {
this . button _left . disabled = false ;
this . button _right . disabled = false ;
2024-04-23 09:48:38 +03:00
this . name _element . disabled = false ;
2024-04-23 05:25:13 +03:00
} ,
randomize : function ( ) {
this . setIndex ( Math . floor ( Math . random ( ) * this . entry _indices . length ) ) ;
} ,
createExportImage : function ( ) {
const entry = this . getSelectedEntry ( ) ;
let img = new Image ( ) ;
img . src = "." + entry [ 1 ] ;
return img ;
} ,
2024-04-23 09:48:38 +03:00
updateOptions : function ( ) {
const options = this . name _element . options ;
for ( let i = 0 ; i < this . entry _indices . length ; i ++ ) {
const index = this . entry _indices [ i ] ;
const entry = this . entries [ index ] ;
if ( options . length > i && options [ i ] . value == entry [ 0 ] ) {
continue ;
} else {
const option = new Option ( entry [ 0 ] , entry [ 0 ] , false , this . selected _index == i ) ;
if ( this . name _element . length <= i ) {
this . name _element . add ( option ) ;
} else {
this . name _element . remove ( i ) ;
this . name _element . add ( option , i ) ;
}
}
}
} ,
2024-04-23 05:25:13 +03:00
} ;
function ColoredPartHandler ( name ) {
PartHandler . call ( this , name ) ;
//For all the different colours of the arms there will be each a own array
this . colored _indices = Object . create ( null ) ;
for ( let i = 0 ; i < color _names . length ; i ++ ) {
this . colored _indices [ color _names [ i ] ] = [ ] ;
}
this . entry _indices = this . colored _indices [ selected _color ] ;
const that = this ;
color _change _callbacks . push ( function ( ) {
that . onColorChange ( ) ;
} ) ;
}
ColoredPartHandler . prototype = Object . assign ( Object . create ( PartHandler . prototype ) , {
constructor : PartHandler ,
fillArray : function ( item ) {
let name = item . name ;
let url = item . url ;
let color = item . color ;
this . entries . push ( [ name , url , color ] ) ; //Two dimensional array, Second dimension holds name on index 0, url at index 1, and color at index 2
} ,
fillIndices : function ( ) {
for ( let i = 0 ; i < this . entries . length ; i ++ ) {
const color = this . entries [ i ] [ 2 ] ;
if ( color == "" ) {
//All colors
for ( let j in this . colored _indices ) {
this . colored _indices [ j ] . push ( i ) ;
}
} else {
const indices = this . colored _indices [ color ] ;
if ( indices == undefined ) {
console . log ( "Cannot register " + this . name + " with unknown color: " + color ) ;
} else {
indices . push ( i ) ;
}
}
}
} ,
onColorChange : function ( ) {
this . entry _indices = this . colored _indices [ selected _color ] ;
this . redraw ( ) ;
} ,
} ) ;
function BodyPartHandler ( name ) {
PartHandler . call ( this , name ) ;
}
BodyPartHandler . prototype = Object . assign ( Object . create ( PartHandler . prototype ) , {
constructor : PartHandler ,
fillArray : ColoredPartHandler . prototype . fillArray ,
setIndex : function ( index ) {
const modulo = this . entry _indices . length ; //Check if index is too big for the array
if ( ! modulo ) {
this . selected _index = 0 ; //Error
} else {
index %= modulo ;
if ( index < 0 ) {
index += modulo ;
}
this . selected _index = index ;
}
this . redraw ( ) ;
const entry = this . getSelectedEntry ( ) ;
selected _color = entry [ 2 ] ; //Global
onColorChange ( ) ; //Global
} ,
} ) ;
const part _handlers = {
body : new BodyPartHandler ( "body" ) ,
eyes : new PartHandler ( "eyes" ) ,
mouth : new PartHandler ( "mouth" ) ,
arms : new ColoredPartHandler ( "arms" ) ,
} ;
2024-04-23 02:36:54 +03:00
// Loading the JSON and getting all the available parts
async function getData ( ) {
fetch ( './parts.json' )
. then ( function ( response ) {
return response . json ( ) ;
} )
. then ( function ( data ) {
loadParts ( data ) ;
} )
. catch ( function ( error ) {
console . log ( 'An error occurred:' , error ) ;
} ) ;
}
2024-04-23 02:02:02 +03:00
2024-04-23 02:36:54 +03:00
function loadParts ( parts ) {
//Load parts into Arrays
2024-04-23 05:25:13 +03:00
for ( const i in part _handlers ) {
parts . type [ i ] . forEach ( function ( p ) { part _handlers [ i ] . fillArray ( p ) ; } ) ;
}
2024-04-23 02:36:54 +03:00
//find the indexes of each part of the corresponding color and write those into the color arrays
2024-04-23 05:25:13 +03:00
for ( const i in part _handlers ) {
part _handlers [ i ] . fillIndices ( ) ;
}
2024-04-23 02:36:54 +03:00
//Randomize initial view
randomize ( ) ;
//Show little statistic
2024-04-23 05:25:13 +03:00
var sum = 0 ;
var variety = 1 ;
for ( const i in part _handlers ) {
sum += part _handlers [ i ] . entries . length ;
variety *= part _handlers [ i ] . entry _indices . length ;
}
2024-04-23 02:36:54 +03:00
stats . innerHTML = "There are " + sum + " Elements available,<br />with " + new Intl . NumberFormat ( "de-DE" ) . format ( variety ) + " possible combinations." ;
//Activate the buttons after everything is loaded in
2024-04-23 05:25:13 +03:00
for ( const i in part _handlers ) {
part _handlers [ i ] . activateControls ( ) ;
}
2024-04-23 02:36:54 +03:00
document . getElementById ( "random" ) . disabled = false ;
document . getElementById ( "export" ) . disabled = false ;
2024-04-23 02:02:02 +03:00
2024-04-23 02:36:54 +03:00
}
2024-04-23 02:02:02 +03:00
2024-04-23 02:36:54 +03:00
function randomize ( ) { //Randomize which parts are shown
2024-04-23 05:25:13 +03:00
for ( const i in part _handlers ) {
part _handlers [ i ] . randomize ( ) ;
2024-04-23 02:36:54 +03:00
}
2024-04-21 23:00:43 +03:00
}
2024-04-23 02:02:02 +03:00
2024-04-23 02:36:54 +03:00
function exportImage ( ) { //Export image so it can be saved as one PNG
let ctx = canvas . getContext ( "2d" ) ;
ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
2024-04-23 05:25:13 +03:00
neomoji _name . value = part _handlers . body . getSelectedEntry ( ) [ 0 ] + "_" + part _handlers . eyes . getSelectedEntry ( ) [ 0 ] + "_" + part _handlers . mouth . getSelectedEntry ( ) [ 0 ] + "_" + part _handlers . arms . getSelectedEntry ( ) [ 0 ] ; //Set name for the emoji to use as the image name and to show as shortcode
let export _layers = [
part _handlers . body . createExportImage ( ) ,
part _handlers . eyes . createExportImage ( ) ,
part _handlers . mouth . createExportImage ( ) ,
part _handlers . arms . createExportImage ( ) ,
] ;
function layerCallback ( ) {
while ( export _layers . length ) {
const layer = export _layers [ 0 ] ;
if ( ! layer . complete ) {
layer . onload = layerCallback ;
return ; //Wait to load
2024-04-23 02:36:54 +03:00
}
2024-04-23 05:25:13 +03:00
//Finished waiting
export _layers . shift ( )
ctx . drawImage ( layer , 0 , 0 , 256 , 256 ) ;
2024-04-19 22:11:07 +03:00
}
2024-04-23 05:25:13 +03:00
let img = canvas . toDataURL ( "image/png" ) ;
export _img . src = img ;
}
setTimeout ( layerCallback , 0 ) ; //Run asynchronously
2024-04-23 02:36:54 +03:00
export _img . hidden = false ;
neomoji _name . hidden = false ;
document . getElementById ( "exportSaveMessage" ) . hidden = false ;
}
2024-04-23 05:25:13 +03:00
NeomojiMixer . PartHandler = PartHandler ;
NeomojiMixer . ColoredPartHandler = ColoredPartHandler ;
NeomojiMixer . BodyPartHandler = BodyPartHandler ;
2024-04-23 02:36:54 +03:00
2024-04-23 05:25:13 +03:00
NeomojiMixer . color _names = color _names ;
NeomojiMixer . color _change _callbacks = color _change _callbacks ;
NeomojiMixer . part _handlers = part _handlers ;
NeomojiMixer . onColorChange = onColorChange ;
2024-04-23 02:36:54 +03:00
NeomojiMixer . getData = getData ;
2024-04-23 05:25:13 +03:00
NeomojiMixer . loadParts = loadParts ;
2024-04-23 02:36:54 +03:00
NeomojiMixer . randomize = randomize ;
NeomojiMixer . exportImage = exportImage ;
2024-04-23 05:25:13 +03:00
NeomojiMixer . canvas = canvas ;
NeomojiMixer . export _img = export _img ;
NeomojiMixer . neomoji _name = neomoji _name ;
NeomojiMixer . stats = stats ;
Object . defineProperty ( NeomojiMixer , 'selected_color' , {
enumerable : true ,
configurable : true ,
get : function ( ) {
return selected _color ;
} ,
set : function ( value ) {
selected _color = value ;
onColorChange ( ) ;
} ,
} ) ;
2024-04-23 02:36:54 +03:00
return NeomojiMixer ;
} ) ( window . NeomojiMixer || { } ) ;
2024-04-23 02:02:02 +03:00
2024-04-19 22:11:07 +03:00
//Main Programm
document . getElementById ( "noJSmessage" ) . hidden = true ;
2024-04-23 02:36:54 +03:00
NeomojiMixer . getData ( ) ;