Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shift to another branch #3

Merged
merged 19 commits into from
May 28, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
make phoneme-item card design more sensible,
add controls,
ui updates,
scramble,
toggles
axolotl authored and aalok-sathe committed May 28, 2020
commit fac03e6473eedfddb49eaad254d95e5a393300ca
4 changes: 3 additions & 1 deletion data/filters.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
voicing:
voice:
- text: voiced
fn: .voiced,.vowel
- text: voiceless
@@ -27,6 +27,8 @@ manner:
fn: .trill
- text: tap or flap
fn: .tap,.flap
- text: lateral
fn: .lateral
- text: fricative
fn: .fricative
- text: affricate
2,234 changes: 1,918 additions & 316 deletions data/phonemes.yaml

Large diffs are not rendered by default.

59 changes: 17 additions & 42 deletions ipatope.css
Original file line number Diff line number Diff line change
@@ -5,6 +5,9 @@ body {
margin: 1%;
}

.hidden {
display: none;
}

/* ---- button ---- */

@@ -18,11 +21,11 @@ body {
cursor: pointer;
}

.button-group > .button:hover {
/* .button-group > .button:hover, .card:hover {
background-color: #8CF;
text-shadow: 0 1px hsla(0, 0%, 100%, 0.5);
color: #222;
}
} */

.button-group > .button:active {
background-color: #28F;
@@ -101,6 +104,8 @@ body {
padding: 10px;
background: #888;
color: #262524;
font-family: 'Ubuntu', sans-serif;
font-weight: lighter;
}

.phoneme-item > * {
@@ -114,7 +119,7 @@ body {
.phoneme-item.is-dragging,
/* Packery adds class while transitioning to drop position */
.phoneme-item.is-positioning-post-drag {
z-index: 2; /* keep dragged item on top */
z-index: 100; /* keep dragged item on top */
outline: 3px dashed #444;
box-shadow: 0 40px 60px rgba(0,0,0,0.45), 0 20px 20px rgba(0,0,0,0.22);
}
@@ -127,57 +132,27 @@ body {
}



.phoneme-item .name {
position: absolute;

left: 10px;
top: 60px;
text-transform: none;
letter-spacing: 0;
font-size: 12px;
font-weight: normal;
}

.phoneme-item .voice {
position: absolute;

left: 10px;
top: 60px;
left: 5%;
top: 50%;
margin-right: 10px;
text-transform: none;
letter-spacing: 0;
font-size: 12px;
font-weight: normal;
}

.phoneme-item .place {
position: absolute;

left: 10px;
top: 75px;
text-transform: none;
letter-spacing: 0;
font-size: 12px;
font-weight: normal;
}

.phoneme-item .manner {
position: absolute;

left: 10px;
top: 90px;
text-transform: none;
letter-spacing: 0;
font-size: 12px;
font-weight: normal;
font-family: 'Ubuntu', sans-serif;
font-weight: lighter;
}

.phoneme-item .symbol {
position: absolute;
left: 10px;
top: 0px;
left: 10%;
top: .1%;
font-size: 42px;
font-weight: bold;
font-family: sans-serif;

color: white;
}

340 changes: 337 additions & 3 deletions ipatope.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// external js: isotope.pkgd.js


// init Isotope
var $grid = $('.grid').isotope({
@@ -91,6 +89,341 @@ $('.sorters').on('click', '.button', function() {
});






$('.button[data-filter~=".voiced,.vowel"]').hover(function(e) {
$('.phoneme-item[class~="voiced"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="voiced"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".voiced,.vowel"]').hover(function(e) {
$('.phoneme-item[class~="vowel"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="vowel"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".voiceless"]').hover(function(e) {
$('.phoneme-item[class~="voiceless"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="voiceless"]').css('outline', '');
$(this).css('outline', '');
});





$('.button[data-filter~=".glottal"]').hover(function(e) {
$('.phoneme-item[class~="glottal"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="glottal"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".velar"]').hover(function(e) {
$('.phoneme-item[class~="velar"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="velar"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".uvular"]').hover(function(e) {
$('.phoneme-item[class~="uvular"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="uvular"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".alveolar,.postalveolar,.alveolo-palatal,.palato-alveolar"]').hover(function(e) {
$('.phoneme-item[class~="alveolar"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="alveolar"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".alveolar,.postalveolar,.alveolo-palatal,.palato-alveolar"]').hover(function(e) {
$('.phoneme-item[class~="postalveolar"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="postalveolar"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".alveolar,.postalveolar,.alveolo-palatal,.palato-alveolar"]').hover(function(e) {
$('.phoneme-item[class~="alveolo-palatal"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="alveolo-palatal"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".alveolar,.postalveolar,.alveolo-palatal,.palato-alveolar"]').hover(function(e) {
$('.phoneme-item[class~="palato-alveolar"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="palato-alveolar"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".palatal,.palato-alveolar,.alveolo-palatar,.palatalised,.labial-palatal"]').hover(function(e) {
$('.phoneme-item[class~="palatal"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="palatal"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".palatal,.palato-alveolar,.alveolo-palatar,.palatalised,.labial-palatal"]').hover(function(e) {
$('.phoneme-item[class~="palato-alveolar"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="palato-alveolar"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".palatal,.palato-alveolar,.alveolo-palatar,.palatalised,.labial-palatal"]').hover(function(e) {
$('.phoneme-item[class~="alveolo-palatar"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="alveolo-palatar"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".palatal,.palato-alveolar,.alveolo-palatar,.palatalised,.labial-palatal"]').hover(function(e) {
$('.phoneme-item[class~="palatalised"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="palatalised"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".palatal,.palato-alveolar,.alveolo-palatar,.palatalised,.labial-palatal"]').hover(function(e) {
$('.phoneme-item[class~="labial-palatal"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="labial-palatal"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".labial,.bilabial,.labiodental,.labiovelar,.labial-palatal"]').hover(function(e) {
$('.phoneme-item[class~="labial"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="labial"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".labial,.bilabial,.labiodental,.labiovelar,.labial-palatal"]').hover(function(e) {
$('.phoneme-item[class~="bilabial"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="bilabial"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".labial,.bilabial,.labiodental,.labiovelar,.labial-palatal"]').hover(function(e) {
$('.phoneme-item[class~="labiodental"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="labiodental"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".labial,.bilabial,.labiodental,.labiovelar,.labial-palatal"]').hover(function(e) {
$('.phoneme-item[class~="labiovelar"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="labiovelar"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".labial,.bilabial,.labiodental,.labiovelar,.labial-palatal"]').hover(function(e) {
$('.phoneme-item[class~="labial-palatal"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="labial-palatal"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".dental,.labiodental"]').hover(function(e) {
$('.phoneme-item[class~="dental"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="dental"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".dental,.labiodental"]').hover(function(e) {
$('.phoneme-item[class~="labiodental"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="labiodental"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".nasal"]').hover(function(e) {
$('.phoneme-item[class~="nasal"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="nasal"]').css('outline', '');
$(this).css('outline', '');
});





$('.button[data-filter~=".stop,.plosive"]').hover(function(e) {
$('.phoneme-item[class~="stop"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="stop"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".stop,.plosive"]').hover(function(e) {
$('.phoneme-item[class~="plosive"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="plosive"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".trill"]').hover(function(e) {
$('.phoneme-item[class~="trill"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="trill"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".tap,.flap"]').hover(function(e) {
$('.phoneme-item[class~="tap"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="tap"]').css('outline', '');
$(this).css('outline', '');
});

$('.button[data-filter~=".tap,.flap"]').hover(function(e) {
$('.phoneme-item[class~="flap"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="flap"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".lateral"]').hover(function(e) {
$('.phoneme-item[class~="lateral"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="lateral"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".fricative"]').hover(function(e) {
$('.phoneme-item[class~="fricative"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="fricative"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".affricate"]').hover(function(e) {
$('.phoneme-item[class~="affricate"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="affricate"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".sibilant"]').hover(function(e) {
$('.phoneme-item[class~="sibilant"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="sibilant"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".approximant"]').hover(function(e) {
$('.phoneme-item[class~="approximant"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="approximant"]').css('outline', '');
$(this).css('outline', '');
});



$('.button[data-filter~=".vowel"]').hover(function(e) {
$('.phoneme-item[class~="vowel"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="vowel"]').css('outline', '');
$(this).css('outline', '');
});





$('.button[data-filter~="sonGreaterThan5"]').hover(function(e) {
$('.phoneme-item[class~="onGreaterThan5"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="onGreaterThan5"]').css('outline', '');
$(this).css('outline', '');
});






// packery --------------------

$('.ui-group').packery({
itemSelector: '.ui-group-item',
gutter: 1,
@@ -141,6 +474,7 @@ function concatArr(arr) {
}


$('.tip').delay(5000).fadeOut('slow');

// --------------- URL __hash__
// function getHashFilter() {
@@ -185,4 +519,4 @@ function concatArr(arr) {
// $(window).on( 'hashchange', onHashchange );
// // trigger event handler to init Isotope
// onHashchange();
// });
// });
7 changes: 6 additions & 1 deletion ipatope.py
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
jinja_env = Environment(loader=FileSystemLoader('templates'),
# extensions=['jinja2_markdown.MarkdownExtension'],
undefined=DebugUndefined)
template = jinja_env.get_template('phonemes.template.html')



class AttrObject:
@@ -37,5 +37,10 @@ def __init__(self, **kwargs):
sorters=sorters,
)

template = jinja_env.get_template('phonemes.template.html')
with Path('index.html').open('w') as out:
out.write(template.render(**data))

code = jinja_env.get_template('ipatope.template.js')
with Path('ipatope.js').open('w') as out:
out.write(code.render(**data))
3 changes: 1 addition & 2 deletions templates/filter.template.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<button type="button" class="ui-group-item btn btn-sm button" data-filter="{{ filter.fn }}">
<!-- <input type="checkbox" class="checkbox btn btn-sm" id="{{ filter.fn }}" name="{{filter.text}}" data-filter="{{ filter.fn }}">
<label class="form-check-label" for="{{ filter.fn }}"> -->
{{filter.text}}
<!-- </label> -->
{{filter.text}}
</button>
206 changes: 206 additions & 0 deletions templates/ipatope.template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@

// init Isotope
var $grid = $('.grid').isotope({
itemSelector: '.phoneme-item',
// layoutMode: 'fitRows',

layoutMode: 'packery',
packery: {
gutter: 2
},
stamp: '.stamp',

getSortData: {
name: '[name]',
symbol: '.symbol',
number: '.number parseInt',
sonority: '.sonority parseFloat',
category: '[data-category]',
weight: function(itemElem) {
var weight = $(itemElem).find('.weight').text();
return parseFloat(weight.replace(/[\(\)]/g, ''));
}
}
});

// filter functions
var filterFns = {
// show if number is greater than 50
numberGreaterThan50: function() {
var number = $(this).find('.number').text();
return parseInt(number, 10) > 50;
},
// show if sonority is greater than 3
sonGreaterThan5: function() {
var number = $(this).find('.sonority').text();
return parseFloat(number, 10) > 5;
},
// show if name ends with -ium
ium: function() {
var name = $(this).find('.name').text();
return name.match(/ium$/);
}
};

filters = {}
// bind filter button click
$('.filters').on('click', '.button', function(event) {
// $checkbox = $(event.currentTarget);
// $button = $checkbox.parent('.button');
$button = $(event.currentTarget);
// get group key
var $buttonGroup = $button.parents('.button-group');
var filterGroup = $buttonGroup.attr('data-filter-group');
// set filter for group
var filterValue = filters[filterGroup] = $button.attr('data-filter');
// try to match function
filters[filterGroup] = filterFns[filterValue] || filters[filterGroup];
// combine filters
if (filterValue in filterFns) {
console.log(filterFns, filterValue);
$grid.isotope({
filter: filterFns[filterValue]
});
} else {
$grid.isotope({
filter: concatValues(filters)
});
}
// set filter for Isotope

});

// change is-checked class on buttons
$('.button-group').each(function(i, buttonGroup) {
var $buttonGroup = $(buttonGroup);
$buttonGroup.on('click', '.button', function(event) {
$buttonGroup.find('.is-checked').removeClass('is-checked');
var $button = $(event.currentTarget);
$button.addClass('is-checked');
});
});

// bind sort button click
$('.sorters').on('click', '.button', function() {
var sortByValue = $(this).attr('data-sort-by');
$grid.isotope({
sortBy: sortByValue
});
});



{% for group, filters in filtergroups.items() %}
{% for filter in filters %}
{% for target in filter.fn.split(',') %}
$('.button[data-filter~="{{ filter.fn }}"]').hover(function(e) {
$('.phoneme-item[class~="{{ target[1:] }}"]').css('outline', '2.5px dashed #444');
$(this).css('outline', '1px dashed #444');
}, function(e) {
$('.phoneme-item[class~="{{ target[1:] }}"]').css('outline', '');
$(this).css('outline', '');
});
{% endfor %}
{% endfor %}
{% endfor %}



// packery --------------------

$('.ui-group').packery({
itemSelector: '.ui-group-item',
gutter: 1,
percentPosition: true
})

// collection of Draggabillies
var draggies = [];
var isDrag = false;

// make all grid-items draggable
$grid.find('.phoneme-item').each(function(i, gridItem) {
var draggie = new Draggabilly(gridItem);
draggies.push(draggie);
// bind drag events to Packery
// $grid.packery( 'bindDraggabillyEvents', draggie );
});


// utils ----------------

let f = (a, b) => [].concat(...a.map(a => b.map(b => [].concat(a, b))));
let cartesian = (a, b, ...c) => b ? cartesian(f(a, b), ...c) : a;


// flatten object by concatting values, making sure to apply demorgans laws ','
function concatValues(obj) {

value = "";
for (var prop in obj) {
var parts = obj[prop].split(",");
var vals = value.split(",");
var newvals = cartesian(parts, vals);

value = newvals.map(x => concatArr(x)).join(',');
}

return value;
}

// flatten object by concatting values
function concatArr(arr) {
var value = '';
for (var v in arr) {
value += arr[v];
}
return value;
}


$('.tip').delay(5000).fadeOut('slow');

// --------------- URL __hash__
// function getHashFilter() {
// var hash = location.hash;
// // get filter=filterName
// var matches = location.hash.match( /filter=([^&]+)/i );
// var hashFilter = matches && matches[1];
// return hashFilter && decodeURIComponent( hashFilter );
// }
//
// $( function() {
//
// var $grid = $('.isotope');
//
// // bind filter button click
// var $filters = $('.filters').on( 'click', '.button', function() {
// var filterAttr = $( this ).attr('data-filter');
// // set filter in hash
// location.hash = 'filter=' + encodeURIComponent( filterAttr );
// });
//
// var isIsotopeInit = false;
//
// function onHashchange() {
// var hashFilter = getHashFilter();
// if ( !hashFilter && isIsotopeInit ) {
// return;
// }
// isIsotopeInit = true;
// // filter isotope
// $grid.isotope({
// itemSelector: '.phoneme-item',
// filter: hashFilter
// });
// // set selected class on button
// if ( hashFilter ) {
// $filters.find('.is-checked').removeClass('is-checked');
// $filters.find('[data-filter="' + hashFilter + '"]').addClass('is-checked');
// }
// }
//
// $(window).on( 'hashchange', onHashchange );
// // trigger event handler to init Isotope
// onHashchange();
// });
145 changes: 83 additions & 62 deletions templates/phonemes.template.html
Original file line number Diff line number Diff line change
@@ -3,90 +3,111 @@
<html>

<head>
<title>
IPAtope
</title>
</head>
<title>
IPAtope
</title>

<body>
<h1>IPAtope</h1>
<!-- CDN -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.js"></script>
<script src="https://rawcdn.githack.com/metafizzy/isotope-packery/0b8522ea7d10e39d084d028da8a81c6f126d6bce/packery-mode.pkgd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://unpkg.com/draggabilly@2/dist/draggabilly.pkgd.min.js"></script>

<h4>Filter</h4>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<link href='http://fonts.googleapis.com/css?family=Ubuntu&subset=latin' rel='stylesheet' type='text/css' />

<div class="filters">
</head>

{% for group, filters in filtergroups.items() %}
<div class="ui-group">
<div class="ui-group-item button-group-label" style="float: left;"><label style="margin-left: 10px; margin-right: 10px;"> {{group}} </label></div>
<div class="button-group" data-filter-group="{{ group }}">
<button class="ui-group-item btn btn-sm button is-checked" data-filter="*">all</button>
{% for filter in filters %}
{% include "filter.template.html" with context %}
<body>
<h1>IPAtope</h1>

<h4>Filter</h4>

<div class="filters">

{% for group, filters in filtergroups.items() %}
<div class="ui-group">
<div class="ui-group-item button-group-label" style="float: left;"><label style="margin-left: 10px; margin-right: 10px;"> {{group}} </label></div>
<div class="button-group" data-filter-group="{{ group }}">
<button class="ui-group-item btn btn-sm button is-checked" data-filter="*">all</button>
{% for filter in filters %}
{% include "filter.template.html" with context %}
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
{% endfor %}

</div>

<h4>Sort</h4>
</div>

<div class="sorters">
<div class="ui-group">
<div class="ui-group-item button-group-label" style="float: left;"><label style="margin-left: 10px; margin-right: 10px;"> sort by </label></div>
<div class="button-group" data-filter-group="{{ group }}">
<button class="ui-group-item btn btn-sm button is-checked" data-sort-by="original-order">original</button>
{% for sorter in sorters %}
{% include "sorter.template.html" with context %}
{% endfor %}
</div>
<h4>Sort</h4>

<div class="sorters">
<div class="ui-group">
<div class="ui-group-item button-group-label" style="float: left;"><label style="margin-left: 10px; margin-right: 10px;"> sort by </label></div>
<div class="button-group" data-filter-group="{{ group }}">
<button class="ui-group-item btn btn-sm button is-checked" data-sort-by="original-order">original</button>
{% for sorter in sorters %}
{% include "sorter.template.html" with context %}
{% endfor %}
</div>
</div>
</div>
</div>

<!-- <div id="sorts" class="button-group"> <button class="button is-checked" data-sort-by="original-order">original order</button>
<!-- <div id="sorts" class="button-group"> <button class="button is-checked" data-sort-by="original-order">original order</button>
<button class="button" data-sort-by="name">name</button>
<button class="button" data-sort-by="symbol">symbol</button>
<button class="button" data-sort-by="sonority">sonority</button>
<button class="button" data-sort-by="category">category</button>
</div> -->

<h4>Controls</h4>
<div class="ui-group">
<div class="controls" style="margin: 5px;">
<button class="ui-group-item btn btn-sm button" type="button" name="button" onclick="$grid.isotope('shuffle');">
shuffle
</button>
<button class="ui-group-item btn btn-sm button" type="button" name="button" onclick="$grid.isotope({sortBy: 'original-order', filter: '*'});">
clear all
</button>
<h4>Controls</h4>
<div class="ui-group-bootstrap">
<div class="controls btn-toolbar" style="margin: 5px;" role="toolbar" aria-label="Toolbar with button groups">
<div class="btn-group mr-2" role="group" aria-label="">
<button class="ui-group-item button btn btn-secondary btn-sm" type="button" name="button" onclick="$grid.isotope({sortBy: 'original-order', filter: '*'});">
reorder
</button>
</div>
<div class="btn-group mr-2" role="group" aria-label="">
<button class="ui-group-item btn btn-secondary btn-sm" type="button" name="button" onclick="$grid.isotope('shuffle');">
shuffle
</button>
<button class="ui-group-item btn btn-secondary btn-sm" type="button" name="button" onclick="$( '.phoneme-item' ).each(function( index ) {
$(this).css({
left : Math.random() * ($(window).width() - $(this).width() - 100),
top : Math.random() * (500 - $(this).height()) - 200,
});
});">
scramble
</button>
</div>
<div class="btn-group mr-2" role="group" aria-label="">
{% for attrtohide in 'name symbol sonority'.split() %}
<button class="ui-group-item btn btn-secondary btn-sm" type="button" name="button"
onclick="$('.phoneme-item>.{{attrtohide}}').toggleClass('hidden');">
toggle {{ attrtohide }}
</button>
{% endfor %}
</div>
</div>
</div>
</div>
<br>
<h5>Try dragging them around!</h5>
<br>
<br>
<h5 class="tip">Try dragging them around!</h5>
<br>

<div class="grid">
{% for phoneme in phonemes %}
{% include "phoneme.template.html" with context %}
{% endfor %}
</div>
<div class="grid">
{% for phoneme in phonemes %}
{% include "phoneme.template.html" with context %}
{% endfor %}
</div>


</body>

<!-- CDN -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.js"></script>
<script src="https://rawcdn.githack.com/metafizzy/isotope-packery/0b8522ea7d10e39d084d028da8a81c6f126d6bce/packery-mode.pkgd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://unpkg.com/draggabilly@2/dist/draggabilly.pkgd.min.js"></script>

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>


<!--LOCAL-->
<link href="ipatope.css" rel="stylesheet" type="text/css">
<script src="ipatope.js"></script>

</html>
</html>