Skip to content

Instantly share code, notes, and snippets.

@allanlaal
Last active July 4, 2018 15:59
Show Gist options
  • Save allanlaal/545c0bd2bc544e2f02a9 to your computer and use it in GitHub Desktop.
Save allanlaal/545c0bd2bc544e2f02a9 to your computer and use it in GitHub Desktop.
var dynamicStyles = false;
var dynamicStylesCache = [];
var dynamicStylesLastId = 0;
/**
*
* @param ruleName string
* @param ruleContents array of key value pairs of CSS rules
* @example
dynamicStyleWrite('.todo_item', [
{
property: "border",
rule: "3px dashed black"
},
{
property: "background-color",
rule: "blue"
},
{
property: "color",
rule: "" // <-- empty value will unset this property
},
]);
*
* @returns null
* @desc highly optimized for minimizing DOM updates. NB! this will not overwrite styles for the same class/id set in CSS files or elsewhere outside dynamic styles
* @author Allan Laal <allan@permanent.ee>
*/
function dynamicStyleWrite(ruleName, ruleContents)
{
log('------------------');
log('DynamicStyles: ' + ruleName + ' ruleContents: ');
console.log(ruleContents);
if (dynamicStyles === false)
{ // iniate container:
var dynamicStylesContainer = document.createElement('style');
document.head.appendChild(dynamicStylesContainer);
dynamicStyles = dynamicStylesContainer.sheet;
}
var ruleCache = [];
var thisIsEdit = false;
if (issetAssoc(ruleName, dynamicStylesCache))
{
ruleCache = getAssoc(ruleName, dynamicStylesCache);
thisIsEdit = true;
log('DynamicStyles: editing existing rule with indexNr: ' + ruleCache.indexNr);
}
else
{
ruleCache = {
id: ruleName,
contents: ruleContents,
indexNr: dynamicStylesLastId
};
dynamicStylesLastId++;
dynamicStylesCache.push(ruleCache);
log('DynamicStyles: adding new rule with indexNr: ' + ruleCache.indexNr);
}
log('DynamicStyles: ruleCache: ');
console.log(ruleCache);
// only update DOM if there is something to change:
var newRules = [];
if (thisIsEdit)
{
log('DynamicStyles: this is edit, checking existing rules');
$(ruleContents).each(function() {
log('DynamicStyles: ' + this.property + ' length is ' + this.rule.length);
if (this.rule.length > 0)
{
currentPair = getAssoc(this.property, ruleCache.contents, 'property');
if (currentPair.length > 0)
{ // editing existing property:
console.log(currentPair);
console.log(currentPair.rule + ' vs ' + this.rule);
if (currentPair.rule != this.rule) // loose comparison, rules are always strings anyway
{
newRules.push(this);
updateAssoc(this.property, this.rule, ruleCache.contents, 'property'); // update cache
}
}
else
{ // adding new property to existing rule:
newRules.push(this);
ruleCache.contents.push(this);
}
}
else
{ // rule is empty, unset!
log('DynamicStyles: ' + this.property + ' is empty (' + this.rule + ')! removing');
removeAssoc(this.property, ruleCache.contents, 'property');
}
});
}
else
{
newRules = ruleCache.contents;
}
log('DynamicStyles: changes to write ');
console.log(newRules);
replaceAssoc(ruleName, ruleCache, dynamicStylesCache, 'id');
var compiledRule = ruleName + ' {';
$(newRules).each(function() {
compiledRule = compiledRule + this.property + ':' + this.rule + ';';
});
compiledRule = compiledRule + '}';
if (thisIsEdit)
{
log('DynamicStyles: deleting dynamic rule index:' + ruleCache.indexNr);
dynamicStyles.deleteRule(ruleCache.indexNr);
}
log ('DynamicStyles: adding dynamic rule: ' + compiledRule);
dynamicStyles.insertRule(compiledRule, ruleCache.indexNr);
return null;
}
/**
*
* @param id string|int
* @param arr array
* @returns bool
* @desc
* @example
* var arrName = [
* {
* id: 1337, <- must alway be set!
* someOtherLabel: dsfdsf,
* },
* {},
* {},
* ]
*
* to check if 1337 is set in arr: issetAssoc(1337, arrName)
*
* @author Allan Laal <allan@permanent.ee>
*/
function issetAssoc(id, arr, keyOverride)
{
var key = 'id';
if (typeof keyOverride !== 'undefined')
{
key = keyOverride;
}
var found = false;
$(arr).each(function () {
if (this[key] === id)
{
found = true;
return false; // break loop
}
});
return found;
}
/**
*
* @param label string
* @param arr array
* @param keyOverride string
* @returns array
* @desc
* @author Allan Laal <allan@permanent.ee>
*/
function getAssoc(label, arr, keyOverride)
{
var key = 'id';
if (typeof keyOverride !== 'undefined')
{
key = keyOverride;
}
var out = [];
$(arr).each(function () {
if (this[key] === label)
{
out = this;
return false; // break loop
}
});
return out;
}
/**
*
* @param label string
* @param arr array
* @param keyOverride string
* @returns array
* @desc replace assoc member with label with value
* @author Allan Laal <allan@permanent.ee>
*/
function replaceAssoc(label, value, arr, keyOverride)
{
var key = 'id';
if (typeof keyOverride !== 'undefined')
{
key = keyOverride;
}
var out = [];
$(arr).each(function () {
if (this[key] === label)
{
out.push(value);
}
else
{
out.push(this);
}
});
return out;
}
/**
*
* @param label string
* @param arr array
* @param keyOverride string
* @returns array
* @desc remove assoc member by label
* @author Allan Laal <allan@permanent.ee>
*/
function removeAssoc(label, arr, keyOverride)
{
var key = 'id';
if (typeof keyOverride !== 'undefined')
{
key = keyOverride;
}
var out = [];
$(arr).each(function () {
if (this[key] !== label)
{
out.push(this);
}
});
return out;
}
/**
*
* @param label string
* @param arr array
* @param keyOverride string
* @returns array
* @desc changes 1 key value, overwrites if exists
* @author Allan Laal <allan@permanent.ee>
*/
function updateAssoc(label, value, arr, keyOverride)
{
var key = 'id';
if (typeof keyOverride !== 'undefined')
{
key = keyOverride;
}
var out = [];
$(arr).each(function () {
if (this[key] === label)
{
var row = this;
row[key] = value;
out.push(row);
}
else
{
out.push(this);
}
});
return out;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment