kinklist/index.html

1659 lines
67 KiB
HTML
Raw Permalink Normal View History

2024-02-11 06:53:10 +00:00
<!DOCTYPE html>
<html>
<head>
<title>Kinklist</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://code.jquery.com/jquery-2.1.4.min.js" integrity="sha256-8WqyJLuWKRBVhxXIL1jBDD7SDxU936oZkCnxQbWwJVw=" crossorigin></script>
<link rel="icon" type="image/x-icon" href="data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAAWdEVYdENyZWF0aW9uIFRpbWUAMTAvMjEvMTV5ehY1AAAAZElEQVQ4jaWTwQ3AIAwDbcT+I9f9hjYQA/mAkO7igKAACWdFAF0A2gb0hP0uCyTATyAJSoaK5xGyEmTC9lktmORUdAQvBQ5cJshktoDk0HkmKRNUEmuE6ztYVXe7bT+jW7z9zi8qYiodCjCHKgAAAABJRU5ErkJggg==">
<style>
body {
font-family: 'Verdana', 'Arial';
font-size: 12px;
}
h2 {
padding: 0;
margin: 0;
margin-top: 10px;
margin-bottom: 5px;
font-size: 18px;
}
table {
border-collapse: collapse;
margin-bottom: 10px;
width: 100%;
}
th {
border: solid #999 1px;
border-right: none;
margin: 0px;
padding: 4px;
background-color: #666;
color: #FFF;
}
th.choicesCol {
box-sizing: border-box;
width: 125px;
}
th + th {
border-left: none;
}
th:last-child {
border-right: solid #999 1px;
}
td {
border-left: solid #999 1px;
border-bottom: solid #999 1px;
border-right: solid #999 1px;
margin: 0px;
padding: 4px;
padding-right: 2px;
}
@-moz-document url-prefix() {
td {
padding: 3.3px;
}
}
td + td {
border-left-style: none;
}
.choice {
box-sizing: border-box;
width: 15px;
height: 15px;
opacity: 0.35;
overflow: hidden;
text-indent: 100px;
border: solid #000 1px;
border-radius: 50%;
outline-style: none!important;
vertical-align: middle;
display: inline-block;
cursor: pointer;
font-size: 0;
padding: 0;
}
.choices .choice {
transition: all 0.3s ease-in-out;
}
.choice + .choice {
margin-left: 5px;
}
.choices .choice:hover {
opacity: 0.75;
}
.choice.selected, .selected > .choice {
opacity: 1;
border-width: 2px;
}
.legend {
vertical-align: middle;
font-size: 14px;
}
.legend div {
display: inline-block;
}
.legend .choice {
opacity: 1;
cursor: default;
}
.legend-text {
vertical-align: middle;
}
#ExportWrapper {
width: 460px;
height: 36px;
}
#URL {
display: none;
position: absolute;
top: 3px;
box-sizing: border-box;
width: 300px;
height: 30px;
border-radius: 4px;
border: solid #CCC 1px;
font-size: 16px;
padding: 10px;
text-align: center;
color: #666;
font-weight: bold;
}
#Export {
position: absolute;
left: 310px;
box-sizing: border-box;
color: #FFF;
text-transform: uppercase;
background-color: #4980ae;
font-size: 18px;
width: 150px;
height: 36px;
border-style: none;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease-in-out;
}
#Export:hover {
opacity: 0.85;
}
#Loading {
display: none;
overflow: visible;
line-height: 26px;
font-size: 16px;
color: #999;
font-weight: bold;
position: absolute;
top: 4px;
left: 220px;
}
#Loading:before {
content: '';
position: absolute;
box-sizing: border-box;
width: 26px;
height: 26px;
border-radius: 50%;
border: solid #999 2px;
border-top-color: transparent;
border-left-color: #CCC;
border-right-color: #666;
animation: spin .5s infinite linear;
margin-left: -40px;
}
@media (min-width: 1700px) {
.legend {
position: absolute;
top: 7px;
left: 160px;
}
.legend div {
width: 130px;
}
#ExportWrapper {
position: absolute;
top: -3px;
right: 46px;
}
h1 {
margin-bottom: 0;
}
}
@media (max-width: 1700px) and (min-width: 800px) {
.legend div {
width: 130px;
padding-bottom: 10px;
}
#ExportWrapper {
position: absolute;
top: -3px;
right: 46px;
}
}
@media (max-width: 800px) and (min-width: 598px) {
.legend div {
width: 180px;
padding-bottom: 10px;
padding-left: 10px;
}
#ExportWrapper {
position: relative;
margin-top: 10px;
margin-left: 5px;
}
#URL {
left: 155px;
width: 190px;
font-size: 10px;
}
#Export {
left: 0px;
}
#Loading {
left: 230px;
}
}
@media (max-width: 597px) {
body {
font-size: 10px;
}
table {
min-width: 345px;
}
.legend div {
width: 150px;
padding-bottom: 10px;
padding-left: 10px;
}
#ExportWrapper {
position: relative;
margin-top: 10px;
margin-left: 0px;
width: 345px;
}
#URL {
left: 155px;
width: 190px;
font-size: 10px;
}
#Export {
left: 0px;
}
#Loading {
left: 230px;
}
}
@keyframes spin {
0% {transform: rotate(0deg);}
100% {transform: rotate(-360deg);}
}
#ExportWrapper :last-child:after {
content: '';
display: block;
clear: both;
}
.kinkCategory {
}
.col {
float: left;
box-sizing: border-box;
margin: 0;
padding: 5px;
}
.col.col25 { width: 25%; }
.col.col33 { width: 33.33333%; }
.col.col50 { width: 50%; }
.col.col100 { width: 100%; padding: 0px; }
.widthWrapper {
max-width: 1700px;
margin-left: auto;
margin-right: auto;
position: relative;
}
#Edit {
width: 18px;
height: 18px;
background-color: transparent;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAAWdEVYdENyZWF0aW9uIFRpbWUAMTAvMTIvMTUsb8MLAAABaElEQVQ4jZWUvY3jMBCF390mzpQ6I1wBS5A6oDuQOxi4Ap4rUAlqwR1M7IhQBYRCR1To7G1giJBkes/7gElGg4/zK7AgVaWI0FpLAIwxlsJWwtbRdR0BrKzruvw9pUTnHEMIP4NCCC8gay2991TVnGVVVSvYCyil9AJ6Z0sY5nJCCEwp5Rc/NefcE6Sqb4OMMRQRigiNMcWSU0pPkIgUIW3b5gmqKkmybdtVzOwnSZRKMcaQJOu6zr66rklylZn3PoO+7vf7P2x0Op2w2+1wuVyybxxHNE0DALjdbgCAaZrweDyw3+/xN8aIvu9hrd3y/qthGHA+n3E4HJDH773/dWnLpmfQdnqfNHs2EeEfkpymCU3TYBiGVerGGByPRwDA9XrFOI7FElX1WZpz7ldLOO9PCCHfIeb7qqrqY9C8hEvlHi1h1lqqKr33xZPZXv4KNMOcc6sX+77/8bdSBJUUY8xZisjqLJb6Bpjss/W5PAkOAAAAAElFTkSuQmCC');
background-repeat: no-repeat;
float: left;
border-style: none;
outline-style: none!important;
margin-top: 6px;
margin-right: 4px;
opacity: 0.5;
cursor: pointer;
}
#Edit:hover {
opacity: 1;
}
.overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.8);
display: none;
}
#EditOverlay #Kinks {
box-sizing: border-box;
position: absolute;
top: 10px;
bottom: 50px;
width: 330px;
left: 50%;
margin-left: -165px;
resize: none;
padding: 10px;
border-radius: 5px;
font-family: monospace, 'Courier new', Courier;
}
#EditOverlay #KinksOK {
box-sizing: border-box;
position: absolute;
bottom: 10px;
width: 330px;
height: 30px;
left: 50%;
margin-left: -165px;
color: #FFF;
text-transform: uppercase;
background-color: #4980ae;
font-size: 18px;
border-style: none;
border-radius: 5px;
cursor: pointer;
}
#InputOverlay {
text-align: center;
white-space: nowrap;
}
#InputOverlay:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.25em;
}
#InputOverlay .widthWrapper {
display: inline-block;
vertical-align: middle;
width: 400px;
text-align: left;
max-width: 100%;
}
#InputOverlay .widthWrapper #InputCurrent, #InputOverlay .widthWrapper .kink-simple {
display: block;
box-sizing: border-box;
padding: 10px;
background-color: #EEE;
}
#InputOverlay .widthWrapper .kink-simple {
position: relative;
height: 40px;
line-height: 20px;
cursor: pointer;
}
#InputOverlay .widthWrapper .kink-simple .choice {
margin-right: 5px;
}
#InputOverlay .widthWrapper .kink-simple .txt-category {
position: absolute;
right: 5px;
top: 5px;
text-transform: uppercase;
font-size: 90%;
font-weight: bold;
opacity: 0.6;
line-height: 1em;
}
#InputOverlay .widthWrapper .kink-simple .txt-field, #InputOverlay .widthWrapper .kink-simple .txt-kink {
vertical-align: middle;
}
#InputOverlay .widthWrapper .kink-simple .txt-field:empty {
display: none;
}
#InputOverlay .widthWrapper .kink-simple .txt-field:before {
content: '(';
}
#InputOverlay .widthWrapper .kink-simple .txt-field:after {
content: ') ';
}
#InputOverlay .widthWrapper #InputPrevious .kink-simple:first-child,
#InputOverlay .widthWrapper #InputNext .kink-simple:nth-child(3) {
background-color: #BBB;
font-size: 10px;
margin-left: 12px;
margin-right: 12px;
height: 33px;
}
#InputOverlay .widthWrapper #InputPrevious .kink-simple:nth-child(2),
#InputOverlay .widthWrapper #InputNext .kink-simple:nth-child(2) {
background-color: #CCC;
font-size: 11px;
margin-left: 6px;
margin-right: 6px;
height: 37px;
}
#InputOverlay .widthWrapper #InputPrevious .kink-simple:nth-child(3),
#InputOverlay .widthWrapper #InputNext .kink-simple:first-child {
background-color: #DDD;
margin-left: 3px;
margin-right: 3px;
}
#InputOverlay .widthWrapper #InputPrevious .kink-simple:first-child {
padding-bottom: 4px;
padding-top: 7px;
}
#InputOverlay .widthWrapper #InputNext .kink-simple:nth-child(3) {
padding-top: 4px;
}
#InputOverlay .widthWrapper #InputPrevious .kink-simple:nth-child(2) {
padding-bottom: 7px;
padding-top: 9px;
}
#InputOverlay .widthWrapper #InputNext .kink-simple:nth-child(2) {
padding-top: 7px;
}
#InputPrevious .kink-simple {
border-top-left-radius: 2px;
border-top-right-radius: 2px;
}
#InputNext .kink-simple {
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
#InputOverlay .widthWrapper #InputCurrent {
position: relative;
}
#InputOverlay .widthWrapper #InputCurrent .closePopup {
position: absolute;
top: 0;
right: 5px;
border-style: none;
background-color: transparent;
font-size: 30px;
cursor: pointer;
outline-style: none!important;
opacity: 0.65;
}
#InputOverlay .widthWrapper #InputCurrent .closePopup:hover {
opacity: 1;
}
#InputOverlay .widthWrapper #InputCurrent h2 {
text-transform: uppercase;
opacity: 0.6;
margin: 0;
}
#InputOverlay .widthWrapper #InputCurrent h3 {
margin-top: 3px;
margin-bottom: 0;
font-size: 14px;
}
#InputOverlay .widthWrapper #InputCurrent #InputValues .big-choice {
padding: 10px;
background-color: rgba(255,255,255,0.75);
border-radius: 4px;
margin-top: 5px;
cursor: pointer;
}
#InputOverlay .widthWrapper #InputCurrent #InputValues .big-choice.selected {
font-weight: bold;
}
#InputOverlay .widthWrapper #InputCurrent #InputValues .big-choice.selected .choice {
opacity: 1;
}
#InputOverlay .widthWrapper #InputCurrent #InputValues .big-choice:hover {
padding: 8px;
border: solid #999 2px;
background-color: rgba(255,255,255,1);
}
#InputOverlay .widthWrapper #InputCurrent #InputValues .big-choice .btn-num-text {
float: right;
display: inline-block;
border: solid #CCC 1px;
text-align: center;
width: 16px;
border-radius: 3px;
}
#StartBtn {
position: absolute;
top: -3px;
right: 5px;
box-sizing: border-box;
width: 36px;
height: 36px;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAAWdEVYdENyZWF0aW9uIFRpbWUAMTAvMTUvMTWxuPuyAAACcElEQVRYhe3X30tTYRzH8fdz3FYTd1xamAuTLDbM3EwqNMnoQgxydVH0A6Ks/oG6Mvp1n1flVUJE3pjUTVPCCJxmEKTWRAuCApujkmhJoZu57ZwuwsCaOx7nbBf73D2H7/PldfjCc54j6CxXSaNI/xvwdzIgrWRAWsmAtJJ2IIOe4iLzejoqmym1lDAZ+UFEicatC8Vm6A++5Jb/Pm+nxlIHatl2keo8FwJBriGHREe8U7bjyrWz7/m51IHq1lWjqire4AAvJkf5qczGrduUvYHTRQdxyQ5dGN0gg8hCBc4MXyUQnliwbqO5kOO2/ZzyXQagONvGcO0DLrxp5m7As3ygxUZB4aTvEt1fnuGSHQgEnoleKnIdEEi8NymQ6h7555nocvJt9jsPJ3o4XFhHq/MaAkFF/xE+hD5p9kwKJLqccZ+HYjMcs9XTXnkdSUi0BToXhYEUnUM7rFvnYRqHryx6b1Ig1T2C6h4h0uDjqK0eSUi4ZAc9VbeRhMS76XFdGFjmkblkB3277yAbc3g/PY7D69bdc9lGNoexGi10fOzG7nWTb7KuLCh8YJAyy2YEgqE997AaLbQFOjnxqom1JiueXTd190xqZOZHOwFoLDrEVCxMm9/D+dfNSELiSVUrpZaSlQXNpTc4wJrHNX/W+SYr5bKdqBr/45soSxqZQWTNW/tDn+etV0umpbT93VtP8awSwZhl4EZZE/7wwgddsdmGJAQxRUktyPt1gIaCvTQU1Ca8eghAVVX6goO6QULPn2vBqnyatpylJm87RrHwu0TVKE+DQ7SMtSe8FSQNWomk3Z06A9JKBqSVDEgraQf6BTg8uT5wSV/pAAAAAElFTkSuQmCC');
border-style: none;
border-radius: 4px;
cursor: pointer;
}
#StartBtn:hover {
opacity: 0.8;
}
@media (max-height: 500px) {
#InputPrevious, #InputNext {
display: none;
}
}
</style>
</head>
<body>
<div class="widthWrapper">
<button id="Edit"></button>
<h1>Kink list</h1>
<div class="legend">
<div><span data-color="#FFFFFF" class="choice notEntered"></span> <span class="legend-text">Not Entered</span></div>
<div><span data-color="#6DB5FE" class="choice favorite"></span> <span class="legend-text">Favorite</span></div>
<div><span data-color="#23FD22" class="choice like"></span> <span class="legend-text">Like</span></div>
<div><span data-color="#FDFD6B" class="choice okay"></span> <span class="legend-text">Okay</span></div>
<div><span data-color="#DB6C00" class="choice maybe"></span> <span class="legend-text">Maybe</span></div>
<div><span data-color="#920000" class="choice no"></span> <span class="legend-text">No</span></div>
</div>
<div id="ExportWrapper">
<input type="text" id="URL">
<button id="Export">Export</button>
<div id="Loading">Loading</div>
</div>
<button id="StartBtn"></button>
<div id="InputList"></div>
</div>
<div id="EditOverlay" class="overlay">
<textarea id="Kinks">
#Partner amount and gender
(General)
* Female/feminine
* Male/masculine
* Neither feminine nor masculine
* One partner
* Two partners (threesome)
* More than two partners (orgy)
#Body preferences
(General)
* Skinny
* Chubby
* Taller than you
* Shorter than you
* Small breasts
* Large breasts
* Small cocks
* Large cocks
* Body hair
* Pubic hair
* Freckles
* Scars
* Smoker
#Body modifications
(General)
* Tattoos
* Scarifications
* Fangs
* Elf ears
* Limb prosthetics
* Piercings - Ears
* Piercings - Face
* Piercings - Body
* Piercings - Genitalia
#Clothing
(Self, Partner)
* Clothed sex
* Lingerie
* Stockings
* Heels
* Leather
* Latex
* Uniform/costume
* Crossdressing
* Spandex/Lycra/elastane
#General
(Giving, Receiving)
* Handjob
* Fingering
* Blowjob
* Deep throat
* Swallowing
* Facials
* Vaginal penetration (with toy or genital)
* Cunnilingus
* Face-sitting
* Edging
* Teasing
* JOI, SI
* Rubbing (e.g. tribadism or frotting)
#Ass play
(Giving, Receiving)
* Anal toys
* Anal penetration
* Rimming
* Double penetration
* Anal fisting
#Restriction
(Self, Partner)
* Light bondage
* Heavy bondage
* Gag
* Blindfold
* Collar
* Leash
* Chastity
* Cuffs
* Spreader bar
* Arm or leg binder/monoglove
* Bondage mittens
* Straightjacket
* Pillory
* Tape
* Rope
* Vacuum bed
* Sleepsack
* Mummification
#Toys
(Self, Partner)
* Dildos
* Plugs
* Vibrators
* Strap-ons
* Sounding
* Fucking machine
#Power exchange
(Dominant, Submissive)
* General D/s
* Domestic servitude
* Finantial dominance/control
* Fear
* Slavery
* Petplay
* Ageplay (e.g. DD or MD/lg or lb)
* Begging
* Forced orgasm
* Orgasm control
* Orgasm denial
#Consensual nonconsent
(Actor, Subject)
* Rape play
* Sleep play
* Free use
* Simulated kidnapping
* Simulated blackmail
* Drugs/intoxication
#Fluids
(General)
* Blood
* Watersports
* Scat
* Lactation
* Cum play
* Spit
* Sweat
* Smell
#Degradation/Humiliation
(Giving, Receiving)
* Consensual "cheating"
* Glory hole
* Name calling
* Body part based insults
* Forced feminization
* Forced masculinization
#Touch & Stimulation
(Giving, Receiving)
* Hugging
* Snuggling/nestling
* Sitting on lap
* Lap pillow
* Kissing
* Tongue kissing
* Smooching
* Licking
* Genital petting/worship
* Ass petting/worship
* Nipple play
* Foot play
* Sensation play
* Tickling
* Wartenberg wheels
#Misc. kinks
(Giving, Receiving)
* Breath play
* Diapers
* Hypnosis
* Outdoors sex
* Breeding
* Food play
* Feeding
#Surrealism (Species)
(Self, Partner)
* Aliens
* Merfolk
* Angels
* Demons
* Werewolves
* Dragons
* Ghosts
* Scaley
* Slime
* Eldritch horrors
* Android
* Harpies
* Nymphs
#Surrealism (Traits)
(Self, Partner)
* Tentacles
* Vore
* Extremely small
* Extremely large
* Feral behavior
* Long tongue
* Fluff
* Horns
* Tails
* Claws
* Kemonomimi
* Fangs
* Beaks
* Wings
* Extra limbs
* Bio-luminiscent
* Transformation
* Mechanical parts
* Self lubrication
* Multiple eyes
* Multiple heads
* Heat
* Knots
* Oviposition
* Inflation
* Flora
* Body swap
#Pain
(Giving, Receiving)
* Light pain
* Heavy pain
* Nipple clamps
* Clothes pins
* Caning
* Flogging
* Beating
* Spanking (with hands)
* Whipping
* Cropping (i.e. with a riding crop)
* Paddling
* Genital slapping
* Genital torture
* Wax play
* Electric stimulation
* Scratching
* Biting
* Cutting
* Hickeys
* Wooden horse (or Spanish donkey)
# Aftercare
(Giving, Receiving)
* Cuddling
* Kissing
* Praising
* Blanket
* Shower together
* Chocolate
</textarea>
<button id="KinksOK">Accept</button>
</div>
<div id="InputOverlay" class="overlay">
<div class="widthWrapper">
<div id="InputPrevious"></div>
<div id="InputCurrent">
<h2 id="InputCategory"></h2>
<h3 id="InputField"></h3>
<button class="closePopup">&times;</button>
<div id="InputValues"></div>
</div>
<div id="InputNext"></div>
</div>
</div>
<script>
var log = function(val, base) {
return Math.log(val) / Math.log(base);
};
var strToClass = function(str){
var className = "";
str = str.toLowerCase();
var validChars = 'abcdefghijklmnopqrstuvwxyz';
var newWord = false;
for(var i = 0; i < str.length; i++) {
var chr = str[i];
if(validChars.indexOf(chr) >= 0) {
if(newWord) chr = chr.toUpperCase();
className += chr;
newWord = false;
}
else {
newWord = true;
}
}
return className;
};
var addCssRule = function(selector, rules){
var sheet = document.styleSheets[0];
if("insertRule" in sheet) {
sheet.insertRule(selector + "{" + rules + "}", 0);
}
else if("addRule" in sheet) {
sheet.addRule(selector, rules, 0);
}
};
var kinks = {};
var inputKinks = {}
var colors = {}
var level = {};
$(function(){
var imgurClientId = '9db53e5936cd02f';
inputKinks = {
$columns: [],
createCategory: function(name, fields){
var $category = $('<div class="kinkCategory">')
.addClass('cat-' + strToClass(name))
.data('category', name)
.append($('<h2>')
.text(name));
var $table = $('<table class="kinkGroup">').data('fields', fields);
var $thead = $('<thead>').appendTo($table);
for(var i = 0; i < fields.length; i++) {
$('<th>').addClass('choicesCol').text(fields[i]).appendTo($thead);
}
$('<th>').appendTo($thead);
$('<tbody>').appendTo($table);
$category.append($table);
return $category;
},
createChoice: function(){
var $container = $('<div>').addClass('choices');
var levels = Object.keys(level);
for(var i = 0; i < levels.length; i++) {
$('<button>')
.addClass('choice')
.addClass(level[levels[i]])
.data('level', levels[i])
.data('levelInt', i)
.attr('title', levels[i])
.appendTo($container)
.on('click', function(){
$container.find('button').removeClass('selected');
$(this).addClass('selected');
});
}
return $container;
},
createKink: function(fields, name){
var $row = $('<tr>').data('kink', name).addClass('kinkRow');
for(var i = 0; i < fields.length; i++) {
var $choices = inputKinks.createChoice();
$choices.data('field', fields[i]);
$choices.addClass('choice-' + strToClass(fields[i]));
$('<td>').append($choices).appendTo($row);
}
$('<td>').text(name).appendTo($row);
$row.addClass('kink-' + strToClass(name));
return $row;
},
createColumns: function(){
var colClasses = ['100', '50', '33', '25'];
var numCols = Math.floor((document.body.scrollWidth - 20) / 400);
if(!numCols) numCols = 1;
if(numCols > 4) numCols = 4;
var colClass = 'col' + colClasses[numCols - 1];
inputKinks.$columns = [];
for(var i = 0; i < numCols; i++){
inputKinks.$columns.push($('<div>').addClass('col ' + colClass).appendTo($('#InputList')));
}
},
placeCategories: function($categories){
var $body = $('body');
var totalHeight = 0;
for(var i = 0; i < $categories.length; i++) {
var $clone = $categories[i].clone().appendTo($body);
var height = $clone.height();;
totalHeight += height;
$clone.remove();
}
var colHeight = totalHeight / (inputKinks.$columns.length);
var colIndex = 0;
for(var i = 0; i < $categories.length; i++) {
var curHeight = inputKinks.$columns[colIndex].height();
var catHeight = $categories[i].height();
if(curHeight + (catHeight / 2) > colHeight) colIndex++;
while(colIndex >= inputKinks.$columns.length) {
colIndex--;
}
inputKinks.$columns[colIndex].append($categories[i]);
}
},
fillInputList: function(){
$('#InputList').empty();
inputKinks.createColumns();
var $categories = [];
var kinkCats = Object.keys(kinks);
for(var i = 0; i < kinkCats.length; i++) {
var catName = kinkCats[i];
var category = kinks[catName];
var fields = category.fields;
var kinkArr = category.kinks;
var $category = inputKinks.createCategory(catName, fields);
var $tbody = $category.find('tbody');
for(var k = 0; k < kinkArr.length; k++) {
$tbody.append(inputKinks.createKink(fields, kinkArr[k]));
}
$categories.push($category);
}
inputKinks.placeCategories($categories);
// Make things update hash
$('#InputList').find('button.choice').on('click', function(){
location.hash = inputKinks.updateHash();
});
},
init: function(){
// Set up DOM
inputKinks.fillInputList();
// Read hash
inputKinks.parseHash();
// Make export button work
$('#Export').on('click', inputKinks.export);
$('#URL').on('click', function(){ this.select(); });
// On resize, redo columns
(function(){
var lastResize = 0;
$(window).on('resize', function(){
var curTime = (new Date()).getTime();
lastResize = curTime;
setTimeout(function(){
if(lastResize === curTime) {
inputKinks.fillInputList();
inputKinks.parseHash();
}
}, 500);
});
})();
},
hashChars: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.=+*^!@",
maxPow: function(base, maxVal) {
var maxPow = 1;
for(var pow = 1; Math.pow(base, pow) <= maxVal; pow++){
maxPow = pow;
}
return maxPow;
},
prefix: function(input, len, char){
while(input.length < len) {
input = char + input;
}
return input;
},
drawLegend: function(context){
context.font = "bold 13px Arial";
context.fillStyle = '#000000';
var levels = Object.keys(colors);
var x = context.canvas.width - 15 - (120 * levels.length);
for(var i = 0; i < levels.length; i++) {
context.beginPath();
context.arc(x + (120 * i), 17, 8, 0, 2 * Math.PI, false);
context.fillStyle = colors[levels[i]];
context.fill();
context.strokeStyle = 'rgba(0, 0, 0, 0.5)'
context.lineWidth = 1;
context.stroke();
context.fillStyle = '#000000';
context.fillText(levels[i], x + 15 + (i * 120), 22);
}
},
setupCanvas: function(width, height, username){
$('canvas').remove();
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
var $canvas = $(canvas);
$canvas.css({
width: width,
height: height
});
// $canvas.insertBefore($('#InputList'));
var context = canvas.getContext('2d');
context.fillStyle = '#FFFFFF';
context.fillRect(0, 0, canvas.width, canvas.height);
context.font = "bold 24px Arial";
context.fillStyle = '#000000';
context.fillText('Kinklist ' + username, 5, 25);
inputKinks.drawLegend(context);
return { context: context, canvas: canvas };
},
drawCallHandlers: {
simpleTitle: function(context, drawCall){
context.fillStyle = '#000000';
context.font = "bold 18px Arial";
context.fillText(drawCall.data, drawCall.x, drawCall.y + 5);
},
titleSubtitle: function(context, drawCall){
context.fillStyle = '#000000';
context.font = "bold 18px Arial";
context.fillText(drawCall.data.category, drawCall.x, drawCall.y + 5);
var fieldsStr = drawCall.data.fields.join(', ');
context.font = "italic 12px Arial";
context.fillText(fieldsStr, drawCall.x, drawCall.y + 20);
},
kinkRow: function(context, drawCall){
context.fillStyle = '#000000';
context.font = "12px Arial";
var x = drawCall.x + 5 + (drawCall.data.choices.length * 20);
var y = drawCall.y - 6;
context.fillText(drawCall.data.text, x, y);
// Circles
for(var i = 0; i < drawCall.data.choices.length; i++){
var choice = drawCall.data.choices[i];
var color = colors[choice];
var x = 10 + drawCall.x + (i * 20);
var y = drawCall.y - 10;
context.beginPath();
context.arc(x, y, 8, 0, 2 * Math.PI, false);
context.fillStyle = color;
context.fill();
context.strokeStyle = 'rgba(0, 0, 0, 0.5)'
context.lineWidth = 1;
context.stroke();
}
}
},
export: function(){
var username = prompt("Please enter your name");
if(typeof username !== 'string') return;
else if (username.length ) username = '(' + username + ')';
$('#Loading').fadeIn();
$('#URL').fadeOut();
// Constants
var numCols = 6;
var columnWidth = 250;
var simpleTitleHeight = 35;
var titleSubtitleHeight = 50;
var rowHeight = 25;
var offsets = {
left: 10,
right: 10,
top: 50,
bottom: 10
};
// Find out how many we have of everything
var numCats = $('.kinkCategory').length;
var dualCats = $('.kinkCategory th + th + th').length;
var simpleCats = numCats - dualCats;
var numKinks = $('.kinkRow').length;
// Determine the height required for all categories and kinks
var totalHeight = (
(numKinks * rowHeight) +
(dualCats * titleSubtitleHeight) +
(simpleCats * simpleTitleHeight)
);
// Initialize columns and drawStacks
var columns = [];
for(var i = 0; i < numCols; i++){
columns.push({ height: 0, drawStack: []});
}
// Create drawcalls and place them in the drawStack
// for the appropriate column
var avgColHeight = totalHeight / numCols;
var columnIndex = 0;
$('.kinkCategory').each(function(){
var $cat = $(this);
var catName = $cat.data('category');
var category = kinks[catName];
var fields = category.fields;
var catKinks = category.kinks;
var catHeight = 0;
catHeight += (fields.length === 1) ? simpleTitleHeight : titleSubtitleHeight;
catHeight += (catKinks.length * rowHeight);
// Determine which column to place this category in
if((columns[columnIndex].height + (catHeight / 2)) > avgColHeight) columnIndex++;
while(columnIndex >= numCols) columnIndex--;
var column = columns[columnIndex];
// Drawcall for title
var drawCall = { y: column.height };
column.drawStack.push(drawCall);
if(fields.length < 2) {
column.height += simpleTitleHeight;
drawCall.type = 'simpleTitle';
drawCall.data = catName;
}
else {
column.height += titleSubtitleHeight;
drawCall.type = 'titleSubtitle';
drawCall.data = {
category: catName,
fields: fields
};
}
// Drawcalls for kinks
$cat.find('.kinkRow').each(function(){
var $kinkRow = $(this);
var drawCall = { y: column.height, type: 'kinkRow', data: {
choices: [],
text: $kinkRow.data('kink')
}};
column.drawStack.push(drawCall);
column.height += rowHeight;
// Add choices
$kinkRow.find('.choices').each(function(){
var $selection = $(this).find('.choice.selected');
var selection = ($selection.length > 0)
? $selection.data('level')
: Object.keys(level)[0];
drawCall.data.choices.push(selection);
});
});
});
var tallestColumnHeight = 0;
for(var i = 0; i < columns.length; i++){
if(tallestColumnHeight < columns[i].height) {
tallestColumnHeight = columns[i].height;
}
}
var canvasWidth = offsets.left + offsets.right + (columnWidth * numCols);
var canvasHeight = offsets.top + offsets.bottom + tallestColumnHeight;
var setup = inputKinks.setupCanvas(canvasWidth, canvasHeight, username);
var context = setup.context;
var canvas = setup.canvas;
for(var i = 0; i < columns.length; i++) {
var column = columns[i];
var drawStack = column.drawStack;
var drawX = offsets.left + (columnWidth * i);
for(var j = 0; j < drawStack.length; j++){
var drawCall = drawStack[j];
drawCall.x = drawX;
drawCall.y += offsets.top;
inputKinks.drawCallHandlers[drawCall.type](context, drawCall);
}
}
//return $(canvas).insertBefore($('#InputList'));
// Send canvas to imgur
$.ajax({
url: 'https://api.imgur.com/3/image',
type: 'POST',
headers: {
// Your application gets an imgurClientId from Imgur
Authorization: 'Client-ID ' + imgurClientId,
Accept: 'application/json'
},
data: {
// convert the image data to base64
image: canvas.toDataURL().split(',')[1],
type: 'base64'
},
success: function(result) {
$('#Loading').hide();
var url = 'https://i.imgur.com/' + result.data.id + '.png';
$('#URL').val(url).fadeIn();
},
fail: function(){
$('#Loading').hide();
alert('Failed to upload to imgur, could not connect');
}
});
},
encode: function(base, input){
var hashBase = inputKinks.hashChars.length;
var outputPow = inputKinks.maxPow(hashBase, Number.MAX_SAFE_INTEGER);
var inputPow = inputKinks.maxPow(base, Math.pow(hashBase, outputPow));
var output = "";
var numChunks = Math.ceil(input.length / inputPow);
var inputIndex = 0;
for(var chunkId = 0; chunkId < numChunks; chunkId++) {
var inputIntValue = 0;
for(var pow = 0; pow < inputPow; pow++) {
var inputVal = input[inputIndex++];
if(typeof inputVal === "undefined") break;
var val = inputVal * Math.pow(base, pow);
inputIntValue += val;
}
var outputCharValue = "";
while(inputIntValue > 0) {
var maxPow = Math.floor(log(inputIntValue, hashBase));
var powVal = Math.pow(hashBase, maxPow);
var charInt = Math.floor(inputIntValue / powVal);
var subtract = charInt * powVal;
var char = inputKinks.hashChars[charInt];
outputCharValue += char;
inputIntValue -= subtract;
}
var chunk = inputKinks.prefix(outputCharValue, outputPow, inputKinks.hashChars[0]);
output += chunk;
}
return output;
},
decode: function(base, output){
var hashBase = inputKinks.hashChars.length;
var outputPow = inputKinks.maxPow(hashBase, Number.MAX_SAFE_INTEGER);
var values = [];
var numChunks = Math.max(output.length / outputPow)
for(var i = 0; i < numChunks; i++){
var chunk = output.substring(i * outputPow, (i + 1) * outputPow);
var chunkValues = inputKinks.decodeChunk(base, chunk);
for(var j = 0; j < chunkValues.length; j++) {
values.push(chunkValues[j]);
}
}
return values;
},
decodeChunk: function(base, chunk){
var hashBase = inputKinks.hashChars.length;
var outputPow = inputKinks.maxPow(hashBase, Number.MAX_SAFE_INTEGER);
var inputPow = inputKinks.maxPow(base, Math.pow(hashBase, outputPow));
var chunkInt = 0;
for(var i = 0; i < chunk.length; i++) {
var char = chunk[i];
var charInt = inputKinks.hashChars.indexOf(char);
var pow = chunk.length - 1 - i;
var intVal = Math.pow(hashBase, pow) * charInt;
chunkInt += intVal;
}
var chunkIntCopy = chunkInt;
var output = [];
for(var pow = inputPow - 1; pow >= 0; pow--) {
var posBase = Math.floor(Math.pow(base, pow));
var posVal = Math.floor(chunkInt / posBase);
var subtract = posBase * posVal;
output.push(posVal);
chunkInt -= subtract;
}
output.reverse();
return output;
},
updateHash: function(){
var hashValues = [];
$('#InputList .choices').each(function(){
var $this = $(this);
var lvlInt = $this.find('.selected').data('levelInt');
if(!lvlInt) lvlInt = 0;
hashValues.push(lvlInt);
});
return inputKinks.encode(Object.keys(colors).length, hashValues);
},
parseHash: function(){
var hash = location.hash.substring(1);
if(hash.length < 10) return;
var values = inputKinks.decode(Object.keys(colors).length, hash);
var valueIndex = 0;
$('#InputList .choices').each(function(){
var $this = $(this);
var value = values[valueIndex++];
$this.children().eq(value).addClass('selected');
});
},
saveSelection: function(){
var selection = [];
$('.choice.selected').each(function(){
// .choice selector
var selector = '.' + this.className.replace(/ /g, '.');
// .choices selector
selector = '.' + $(this).closest('.choices')[0].className.replace(/ /g, '.') + ' ' + selector;
// .kinkRow selector
selector = '.' + $(this).closest('tr.kinkRow')[0].className.replace(/ /g, '.') + ' ' + selector;
// .kinkCategory selector
selector = '.' + $(this).closest('.kinkCategory')[0].className.replace(/ /g, '.') + ' ' + selector;
selector = selector.replace('.selected', '');
selection.push(selector);
});
return selection;
},
inputListToText: function(){
var KinksText = "";
var kinkCats = Object.keys(kinks);
for(var i = 0; i < kinkCats.length; i++){
var catName = kinkCats[i];
var catFields = kinks[catName].fields;
var catKinks = kinks[catName].kinks;
KinksText += '#' + catName + "\r\n";
KinksText += '(' + catFields.join(', ') + ")\r\n";
for(var j = 0; j < catKinks.length; j++){
KinksText += '* ' + catKinks[j] + "\r\n";
}
KinksText += "\r\n";
}
return KinksText;
},
restoreSavedSelection: function(selection){
setTimeout(function(){
for(var i = 0; i < selection.length; i++){
var selector = selection[i];
$(selector).addClass('selected');
}
location.hash = inputKinks.updateHash();
}, 300);
},
parseKinksText: function(kinksText){
var newKinks = {};
var lines = kinksText.replace(/\r/g, '').split("\n");
var cat = null;
var catName = null;
for(var i = 0; i < lines.length; i++){
var line = lines[i];
if(!line.length) continue;
if(line[0] === '#') {
if(catName){
if(!(cat.fields instanceof Array) || cat.fields.length < 1){
alert(catName + ' does not have any fields defined!');
return;
}
if(!(cat.kinks instanceof Array) || cat.kinks.length < 1){
alert(catName + ' does not have any kinks listed!');
return;
}
newKinks[catName] = cat;
}
catName = line.substring(1).trim();
cat = { kinks: [] };
}
if(!catName) continue;
if(line[0] === '(') {
cat.fields = line.substring(1, line.length - 1).trim().split(',');
for(var j = 0; j < cat.fields.length; j++){
cat.fields[j] = cat.fields[j].trim();
}
}
if(line[0] === '*'){
var kink = line.substring(1).trim();
cat.kinks.push(kink);
}
}
if(catName && !newKinks[catName]){
if(!(cat.fields instanceof Array) || cat.fields.length < 1){
alert(catName + ' does not have any fields defined!');
return;
}
if(!(cat.kinks instanceof Array) || cat.kinks.length < 1){
alert(catName + ' does not have any kinks listed!');
return;
}
newKinks[catName] = cat;
}
return newKinks;
}
};
$('#Edit').on('click', function(){
var KinksText = inputKinks.inputListToText();
$('#Kinks').val(KinksText.trim());
$('#EditOverlay').fadeIn();
});
$('#EditOverlay').on('click', function(){
$(this).fadeOut();
});
$('#KinksOK').on('click', function(){
var selection = inputKinks.saveSelection();
try {
var kinksText = $('#Kinks').val();
kinks = inputKinks.parseKinksText(kinksText);
inputKinks.fillInputList();
}
catch(e){
alert('An error occured trying to parse the text entered, please correct it and try again');
return;
}
inputKinks.restoreSavedSelection(selection);
$('#EditOverlay').fadeOut();
});
$('.overlay > *').on('click', function(e){
e.stopPropagation();
});
var stylesheet = document.styleSheets[0];
$('.legend .choice').each(function(){
var $choice = $(this);
var $parent = $choice.parent();
var text = $parent.text().trim();
var color = $choice.data('color');
var cssClass = this.className.replace('choice ', '').trim();
addCssRule('.choice.' + cssClass, 'background-color: ' + color + ';');
colors[text] = color;
level[text] = cssClass;
});
kinks = inputKinks.parseKinksText($('#Kinks').text().trim());
inputKinks.init();
(function(){
var $popup = $('#InputOverlay');
var $previous = $('#InputPrevious');
var $next = $('#InputNext');
// current
var $category = $('#InputCategory');
var $field = $('#InputField');
var $options = $('#InputValues');
function getChoiceValue($choices){
var $selected = $choices.find('.choice.selected');
return $selected.data('level');
}
function getChoicesElement(category, kink, field){
var selector = '.cat-' + strToClass(category);
selector += ' .kink-' + strToClass(kink);
selector += ' .choice-' + strToClass(field);
var $choices = $(selector);
return $choices;
}
inputKinks.getAllKinks = function(){
var list = [];
var categories = Object.keys(kinks);
for(var i = 0; i < categories.length; i++){
var category = categories[i];
var fields = kinks[category].fields;
var kinkArr = kinks[category].kinks;
for(var j = 0; j < fields.length; j++) {
var field = fields[j];
for(var k = 0; k < kinkArr.length; k++){
var kink = kinkArr[k];
var $choices = getChoicesElement(category, kink, field);
var value = getChoiceValue($choices);
var obj = { category: category, kink: kink, field: field, value: value, $choices: $choices, showField: (fields.length >= 2)};
list.push(obj);
}
}
}
return list;
};
inputKinks.inputPopup = {
numPrev: 3,
numNext: 3,
allKinks: [],
kinkByIndex: function(i){
var numKinks = inputKinks.inputPopup.allKinks.length;
i = (numKinks + i) % numKinks;
return inputKinks.inputPopup.allKinks[i];
},
generatePrimary: function(kink){
var $container = $('<div>');
var btnIndex = 0;
$('.legend > div').each(function(){
var $btn = $(this).clone();
$btn.addClass('big-choice');
$btn.appendTo($container);
$('<span>')
.addClass('btn-num-text')
.text(btnIndex++)
.appendTo($btn)
var text = $btn.text().trim().replace(/[0-9]/g, '');
if(kink.value === text) {
$btn.addClass('selected');
}
$btn.on('click', function(){
$container.find('.big-choice').removeClass('selected');
$btn.addClass('selected');
kink.value = text;
$options.fadeOut(200, function(){
$options.show();
inputKinks.inputPopup.showNext();
});
var choiceClass = strToClass(text);
kink.$choices.find('.' + choiceClass).click();
});
});
return $container;
},
generateSecondary: function(kink){
var $container = $('<div class="kink-simple">');
$('<span class="choice">').addClass(level[kink.value]).appendTo($container);
$('<span class="txt-category">').text(kink.category).appendTo($container);
if(kink.showField){
$('<span class="txt-field">').text(kink.field).appendTo($container);
}
$('<span class="txt-kink">').text(kink.kink).appendTo($container);
return $container;
},
showIndex: function(index){
$previous.html('');
$next.html('');
$options.html('');
$popup.data('index', index);
// Current
var currentKink = inputKinks.inputPopup.kinkByIndex(index);
var $currentKink = inputKinks.inputPopup.generatePrimary(currentKink);
$options.append($currentKink);
$category.text(currentKink.category);
$field.text((currentKink.showField ? '(' + currentKink.field + ') ' : '') + currentKink.kink);
$options.append($currentKink);
// Prev
for(var i = inputKinks.inputPopup.numPrev; i > 0; i--){
var prevKink = inputKinks.inputPopup.kinkByIndex(index - i);
var $prevKink = inputKinks.inputPopup.generateSecondary(prevKink);
$previous.append($prevKink);
(function(skip){
$prevKink.on('click', function(){
inputKinks.inputPopup.showPrev(skip);
});
})(i);
}
// Next
for(var i = 1; i <= inputKinks.inputPopup.numNext; i++){
var nextKink = inputKinks.inputPopup.kinkByIndex(index + i);
var $nextKink = inputKinks.inputPopup.generateSecondary(nextKink);
$next.append($nextKink);
(function(skip){
$nextKink.on('click', function(){
inputKinks.inputPopup.showNext(skip);
});
})(i);
}
},
showPrev: function(skip){
if(typeof skip !== "number") skip = 1;
var index = $popup.data('index') - skip;
var numKinks = inputKinks.inputPopup.allKinks.length;
index = (numKinks + index) % numKinks;
inputKinks.inputPopup.showIndex(index);
},
showNext: function(skip){
if(typeof skip !== "number") skip = 1;
var index = $popup.data('index') + skip;
var numKinks = inputKinks.inputPopup.allKinks.length;
index = (numKinks + index) % numKinks;
inputKinks.inputPopup.showIndex(index);
},
show: function(){
inputKinks.inputPopup.allKinks = inputKinks.getAllKinks();
inputKinks.inputPopup.showIndex(0);
$popup.fadeIn();
}
};
$(window).on('keydown', function(e){
if(e.altKey || e.shiftKey || e.ctrlKey) return;
if(!$popup.is(':visible')) return;
if(e.keyCode === 38) {
inputKinks.inputPopup.showPrev();
e.preventDefault();
e.stopPropagation();
}
if(e.keyCode === 40) {
inputKinks.inputPopup.showNext();
e.preventDefault();
e.stopPropagation();
}
var btn = -1;
if(e.keyCode >= 96 && e.keyCode <= 101) {
btn = e.keyCode - 96;
}
else if(e.keyCode >= 48 && e.keyCode <= 53) {
btn = e.keyCode - 48;
}
else {
return;
}
var $btn = $options.find('.big-choice').eq(btn);
$btn.click();
});
$('#StartBtn').on('click', inputKinks.inputPopup.show);
$('#InputCurrent .closePopup, #InputOverlay').on('click', function(){
$popup.fadeOut();
});
})();
});
</script>
</body>
</html>