A Pen by josh bowling on CodePen.
Created
December 4, 2018 19:33
-
-
Save joshuaebowling/3deeb1f5d8ce40ad8a83199c261ae9fe to your computer and use it in GitHub Desktop.
teamoji
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script type="text/template" id="tmpl-cell"> | |
<div class="input mb-2"> | |
<input data-bind="value: character, attr: {id: 'clip-'+name(), 'data-clipboard-target':'#clip-'+name(), title: name()}" type="text" class="form-control box1" placeholder="" aria-label="" aria-describedby="basic-addon1"> | |
</div> | |
</script> | |
<script type="text/template" id="tmpl-snippet"> | |
<div> | |
<input class="box3 fsnippet" data-bind="value: value, attr: {id: 'snippet-'+id()}" /> | |
<button class="btn" data-bind="attr: {'data-clipboard-target':'#snippet-'+id()}"> | |
<i class="fa fa-copy"></i> | |
</button> | |
<button class="btn" data-bind="click: () => {$parent.remove($parent)}"> | |
<i class="fa fa-minus" ></i> | |
</button> | |
</div> | |
</script> | |
<script type="text/template" id="tmpl-grid"> | |
<div class="wrapper" data-bind="foreach: collection"> | |
<special-character params="character: character, name: name" /> | |
</div> | |
</script> | |
<script type="text/template" id="tmpl-snippets"> | |
<div class="input-group mb-3"> | |
<input class="form-control box2" placeholder="add new snippet" data-bind="value: newSnippetValue"/> | |
<div class="input-group-append"> | |
<button class="btn btn-outline-secondary"data-bind="click: add"> | |
<i class="fa fa-plus" ></i> | |
</button> | |
</div> | |
</div> | |
<div data-bind="foreach: collection"> | |
<snippet params="snippetModel: $data" /> | |
</div> | |
</script> | |
<div class="py-5 text-center"> | |
<h2>Teamoji</h2> | |
<p class="lead">an emoji, special character, and snippets app</p> | |
<p>Click On Any Item to Copy It</p> | |
</div> | |
<div id="app" class="container h-100 py-2"> | |
<ul class="nav nav-tabs border-0" id="myTab" role="tablist"> | |
<li class="nav-item"> | |
<a class="nav-link border border-primary border-bottom-0" id="character-tab" data-toggle="tab" href="#characters" role="tab" aria-controls="home">Characters</a> | |
</li> | |
<li class="nav-item"> | |
<a class="nav-link active border border-warning border-bottom-0" id="emoji-tab" data-toggle="tab" href="#emojis" role="tab" aria-controls="emojis" >Emojis</a> | |
</li> | |
<li class="nav-item"> | |
<a class="nav-link border border-danger border-bottom-0" id="snippet-tab" data-toggle="tab" href="#snippets" role="tab" aria-controls="snippets" >Snippets</a> | |
</li> | |
</ul> | |
<div class="tab-content" id="myTabContent"> | |
<div class="tab-pane h-100 p-3 border border-primary" id="characters" role="tabpanel" aria-labelledby="character-tab"> | |
<div class="well"> | |
<div class="wrapper-special-character"> | |
<special-characters /> | |
</div> | |
</div> | |
</div> | |
<div class="tab-pane h-100 p-3 active border border-warning" id="emojis" role="tabpanel" aria-labelledby="emojis-tab"> | |
<div class="well"> | |
<div class="wrapper wrapper-emojis"> | |
<emojis /> | |
</div> | |
</div> | |
</div> | |
<div class="tab-pane h-100 p-3 border border-danger" id="snippets" role="tabpanel" aria-labelledby="snippets-tab"> | |
<div class="well"> | |
<div class="wrapper-snippet"> | |
<snippets /> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const chars = _.map(["±", "®", "¶", "§", "µ", "¢", "£", "¤", "¥", "¦", "§", "¨", "©", "«", "¬", "°", "¼", "½", "¿", "×", "√","∑", "∫", "∞"], (character, i) => ({name:`char-${i}`, character})); | |
const store = new Basil({ | |
namespace: 'teamoji', | |
storages: ['cookie', 'local'], | |
storage: 'local', | |
expireDays: 365 | |
}); | |
const root = { | |
snippets: ko.observableArray() | |
}; | |
const Store = (KEY, overrides = {}) => { | |
const result = { | |
find: (crit) => { | |
var items = result.fetch(); | |
return items.find(snip => snip.value === crit || snip.id === crit); | |
}, | |
createModel: (value = "") => ({value, order: -1, id: -1}) | |
, | |
update: (snippet) => { | |
if(snippet.value === "") return; | |
const snippets = result.fetch(); | |
const found = result.find(snippet.id); | |
if(!found) { | |
snippet.id = result.nextId(); | |
snippet.order = snippet.id; | |
snippets.push(snippet); | |
} else { | |
snippets[result.getIndex(snippet)] = snippet; | |
} | |
store.set(KEY, snippets); | |
}, | |
getIndex: (snippet) => result.fetch().map(snip => snip.id).indexOf(snippet.id) + 1 | |
, | |
remove: (snippet) => { | |
const snippets = result.fetch(); | |
_.remove(snippets, (snip) => snip.id === snippet.id); | |
store.set(KEY, snippets); | |
}, | |
fetch: () => { | |
const fetched = store.get(KEY) || []; | |
return _.orderBy(fetched, "order"); | |
}, | |
nextId: () => { | |
var last = _.last(result.fetch()); | |
return (last ? last['id'] : 0) + 1; | |
}, | |
reset: () => store.set(KEY, null) | |
}; | |
return _.assign({}, result, overrides); | |
}; | |
const charStore = window.charStore = (() => { | |
const _charStore = { | |
createModel:(character) => ({character, order: -1, id: -1}), | |
find: (crit) => { | |
var items = result.fetch(); | |
return items.find(char => char.character === crit || char.id === crit); | |
} | |
} | |
return Store('special-characters', _charStore); | |
})(); | |
const snippetStore = Store('snippets'); | |
ko.components.register('special-character', { | |
template: $('#tmpl-cell').html(), | |
viewModel: function (props) { | |
var vm = { | |
character: ko.observable(props.character), | |
name: ko.observable(props.name) | |
}; | |
return vm; | |
} | |
}); | |
ko.components.register('snippet', { | |
template: $('#tmpl-snippet').html(), | |
viewModel: function (props) { | |
var vm = { | |
value: ko.observable(props.snippetModel.value), | |
id: ko.observable(props.snippetModel.id), | |
order: ko.observable(props.snippetModel.order) | |
}; | |
return vm; | |
} | |
}); | |
ko.components.register('special-characters', { | |
template: $('#tmpl-grid').html(), | |
viewModel: function (props) { | |
var vm = { | |
collection: ko.observableArray(chars) | |
}; | |
return vm; | |
} | |
}); | |
ko.components.register('emojis', { | |
template: $('#tmpl-grid').html(), | |
viewModel: function (props) { | |
var vm = { | |
collection: ko.observableArray(emojis) | |
}; | |
return vm; | |
} | |
}); | |
ko.components.register('snippets', { | |
template: $('#tmpl-snippets').html(), | |
viewModel: function (props) { | |
var vm = { | |
collection: ko.observable([]), | |
update: (snippet) => { | |
snippetStore.update(snippet); | |
vm.refetch(); | |
}, | |
remove: (snippet) => { | |
snippetStore.remove(snippet); | |
vm.refetch(); | |
}, | |
refetch: () => { | |
vm.collection(fetch()); | |
}, | |
add:() => { | |
var model = snippetStore.createModel(vm.newSnippetValue()); | |
snippetStore.update(model); | |
vm.newSnippetValue(''); | |
vm.refetch(); | |
}, | |
newSnippetValue: ko.observable('') | |
}; | |
const fetch = () => _.map(snippetStore.fetch(), snip => _.assign({remove: vm.remove, update:vm.update}, snip)); | |
vm.collection(fetch()); | |
return vm; | |
} | |
}); | |
(($) => { | |
ko.applyBindings(root, $('#app')[0]); | |
var clipboard = new ClipboardJS('.box1'); | |
})(jQuery); | |
const _emojis = { | |
"hello":"( ͡° ͜ʖ ͡°)" | |
,"shrug face ":"¯\\_(ツ)_/¯" | |
,"meh":"¯\\(°_o)/¯" | |
,"squinty":"( ^_^)" | |
,"confused ":"¿ⓧ_ⓧﮌ" | |
,"confused scratch":"(⊙.☉)7" | |
,"zoned":"(⊙_◎)" | |
,"crazy":"ミ●﹏☉ミ" | |
,"seal":"(ᵔᴥᵔ)" | |
,"Winning!":"(•̀ᴗ•́)و ̑̑" | |
,"wizard":"(∩`-´)⊃━☆゚.*・。゚" | |
,"Zombie":"[¬º-°]¬" | |
,"eh":"゜-゜" | |
,"innocent face ":"ʘ‿ʘ" | |
,"cute bear ":"ʕ•ᴥ•ʔ" | |
,"squinting bear":"ʕᵔᴥᵔʔ" | |
,"GTFO Bear":"ʕ •`ᴥ•´ʔ" | |
,"cute face with big eyes ":"(。◕‿◕。)" | |
,"surprised / loudmouthed ":"( ゚Д゚)" | |
,"feel perky ":"(`・ω・´)" | |
//,"angry face":"(╬ ಠ益ಠ)" | |
,"excited ":"☜(⌒▽⌒)☞" | |
,"happy face ":"ヽ(´▽`)/" | |
,"basking in glory ":"ヽ(´ー`)ノ" | |
,"kitty emote":"ᵒᴥᵒ#" | |
,"fido":"V•ᴥ•V" | |
,"meow":"ฅ^•ﻌ•^ฅ" | |
,"flexing ":"ᕙ(⇀‸↼‶)ᕗ" | |
,"do you even lift bro?":"ᕦ(ò_óˇ)ᕤ" | |
,"kirby":"⊂(◉‿◉)つ" | |
,"tripping out ":"q(❂‿❂)p" | |
,"discombobulated ":"⊙﹏⊙" | |
,"sad and confused ":"¯\\_(⊙︿⊙)_/¯" | |
,"worried":"(´・_・`)" | |
,"dear god why ":"щ(゚Д゚щ)" | |
,"staring ":"٩(๏_๏)۶" | |
,"strut":"ᕕ( ᐛ )ᕗ" | |
,"angry troll":"ヽ༼ ಠ益ಠ ༽ノ" | |
,"cry face":"。゚( ゚இ‸இ゚)゚。" | |
,"cry troll":"༼ ༎ຶ ෴ ༎ຶ༽" | |
,"TGIF":"“ヽ(´▽`)ノ”" | |
,"dancing ":"┌(ㆆ㉨ㆆ)ʃ" | |
,"angry birds":"( ఠൠఠ )ノ" | |
,"no support ":"乁( ◔ ౪◔)「" | |
,"shy ":"(๑•́ ₃ •̀๑) " | |
,"fly away":"⁽⁽ଘ( ˊᵕˋ )ଓ⁾⁾" | |
,"careless":"◔_◔" | |
,"Heart":"♥" | |
,"shark face / jagged mustache":"( ˇ෴ˇ )" | |
,"emo dance ":"ヾ(-_- )ゞ" | |
,"dance ":"♪♪ ヽ(ˇ∀ˇ )ゞ" | |
,"opera":"ヾ(´〇`)ノ♪♪♪" | |
,"winnie the pooh":"ʕ •́؈•̀)" | |
,"fight":"(ง'̀-'́)ง" | |
,"listening to headphones":"◖ᵔᴥᵔ◗ ♪ ♫ " | |
,"robot":"{•̃_•̃}" | |
,"questionable / dislike":"(Ծ‸ Ծ)" | |
,"pointing":"(☞゚ヮ゚)☞" | |
,"chasing / running away":"''⌐(ಠ۾ಠ)¬'''" | |
,"whistling / music":"(っ•́。•́)♪♬" | |
,"injured":"(҂◡_◡) " | |
,"eye roll":"⥀.⥀" | |
,"flying":"ح˚௰˚づ " | |
,"things that can't be unseen":"♨_♨" | |
,"looking down":"(._.)" | |
,"yum":"(っ˘ڡ˘ς)" | |
,"judging":"( ఠ ͟ʖ ఠ)" | |
,"satisfied":"(◠﹏◠)" | |
,"sad and crying":"(ᵟຶ︵ ᵟຶ)" | |
,"chicken":"ʚ(•`" | |
,"straining":"(⩾﹏⩽)" | |
,"Happy Hug":"\\(ᵔᵕᵔ)/" | |
,"doe eyes happy":"◕‿◕" | |
}; | |
var emojis = _.map(_.keys(_emojis), (k) =>({name:_.camelCase(k), character:_emojis[k]})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.4/clipboard.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/basil.js/0.4.10/basil.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/masonry/4.2.2/masonry.pkgd.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/draggable/1.0.0-beta.8/draggable.min.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body,html { | |
height: 100%; | |
} | |
#app { | |
width:350px; | |
} | |
/* when not active use specificity to override the !important on border-(color) */ | |
.nav-tabs .nav-link:not(.active) { | |
border-color: transparent !important; | |
} | |
.box { | |
background-color: #444; | |
color: #fff; | |
border-radius: 5px; | |
padding: 10px; | |
font-size: 150%; | |
} | |
.box:nth-child(even) { | |
background-color: #ccc; | |
color: #000; | |
} | |
.wrapper { | |
width: 300px; | |
display: grid; | |
grid-gap: 5px; | |
grid-template-columns: repeat(2, 150px); | |
height: 500px; | |
overflow-y: auto; | |
overflow-x:hidden; | |
} | |
.wrapper-special-character { | |
width: 290px; | |
display: grid; | |
grid-gap: 5px; | |
grid-template-columns: repeat(2, 140px); | |
} | |
.wrapper-snippet { | |
width: 300px; | |
} | |
.fa { | |
font-size:10px; | |
} | |
input { | |
width: 90px; | |
} | |
input.snippet { | |
width: 200px; | |
} | |
h1 { | |
font-size: 25px; | |
} | |
h1 > sub { | |
font-size:10px; | |
} | |
.wrapper-special-character input[type=text]:focus { | |
box-shadow: 0 0 5px rgba(81, 203, 238, 1); | |
border: 2px solid rgba(81, 203, 238, 1); | |
} | |
.wrapper-special-character input[type=text]:hover { | |
box-shadow: 0 0 5px rgba(81, 203, 238, 1); | |
border: 2px solid rgba(81, 203, 238, 1); | |
} | |
.wrapper-emojis input[type=text]:focus { | |
box-shadow: 0 0 5px rgb(237, 173, 26); | |
border: 2px solid rgb(237, 173, 26); | |
} | |
.wrapper-emojis input[type=text]:hover { | |
box-shadow: 0 0 5px rgb(237, 173, 26); | |
border: 2px solid rgb(237, 173, 26); | |
} | |
.box1 { | |
background-color: #e6e9ef; | |
color: #000; | |
border-radius: 5px; | |
padding: 5px; | |
font-size: 100%; | |
width: 140px; | |
} | |
.box2 { | |
background-color: #e6e9ef; | |
color: #000; | |
border-radius: 5px; | |
padding: 5px; | |
font-size: 100%; | |
width: 120px; | |
} | |
.box3 { | |
color: #000; | |
font-size: 100%; | |
width: 220px; | |
border: 1px; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" /> | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" /> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment