%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/tjamichg/cursos.tjamich.gob.mx/main/inc/lib/javascript/badge-studio/media/js/
Upload File :
Create Path :
Current File : //home/tjamichg/cursos.tjamich.gob.mx/main/inc/lib/javascript/badge-studio/media/js/studio.js

// set superglobal js var by default 100 for glyph
window.size = 'medium';

var SVG_NS = "http://www.w3.org/2000/svg";

var svgCache = {};
var options = {};

var $badge;
var $badgeRaster;
var $studio = document.getElementById('studio');

var $template = document.getElementById('studio-template');
var $palette = document.getElementById('studio-palette');
var $mask = document.getElementById('studio-mask');
var $glyph = document.getElementById('studio-glyph');

var $glyphSelector;
var $glyphSelectorButton;

window.addEventListener('load', function init() {

    $badgeRaster = new Image();
    $badgeRaster.id = 'raster';
    document.getElementById('output').appendChild($badgeRaster);

    $template.addEventListener('change', updateTemplate);
    $palette.addEventListener('change', updatePalette);
    $mask.addEventListener('change', updateMask);
    $glyph.addEventListener('change', updateGlyph);

    initStudio();
    initPalettes();
    initOptions();
    updateTemplate();

});

// ==[ General Methods ]======================================================

/**
 *
 */
function showError(err) {
    // TO DO - show errors :)
    console.err(err);
}

// ==[ Studio ]===============================================================

/**
 *
 */
function initStudio() {

    initGlyphSelector();

    document.addEventListener('keydown', function (event) {
        if (event.keyCode === 27) { // Escape
            if ($glyphSelector && $glyphSelector.offsetWidth)
                closeGlyphSelector();
        }
    }, true);

    document.addEventListener('focus', function (event) {
        [$glyphSelector].forEach(function ($overlay) {
            if ($overlay && $overlay.offsetWidth && !$overlay.contains(event.target)) {
                event.stopPropagation();
                $overlay.focus();
            }
        });
    }, true);
}

// ==[ Glyph Selector ]=======================================================

/**
 *
 */
function initGlyphSelector() {

    if ($glyphSelector) {
        return false;
    }

    var glyphLog = [];

    $glyphSelectorButton = document.createElement('button');
    $glyphSelectorButton.className = 'btn btn-default pull-right';
    $glyphSelectorButton.id = 'search-glyphs';
    $glyphSelectorButton.type = 'button';
    $glyphSelectorButton.innerHTML = '<em class="fa fa-search"></em> Search';
    $glyphSelectorButton.addEventListener('click', openGlyphSelector);

    $glyph.parentNode.insertBefore($glyphSelectorButton, $glyph.nextSibling);

    var $$options = $glyph.querySelectorAll('option');

    $glyphSelector = importTemplate('glyph-selector', function ($template) {

        var $list = $template.querySelector('ul');

        for (var i = 0, l = $$options.length; i < l; i++) {
            (function ($option, index) {
                var value = $option.value;
                var id = 'glyph-selector-item-' + value;

                var $node = importTemplate('glyph-selector-item', function ($template) {
                    var $input = $template.querySelector('input');
                    $input.id = id;
                    $input.value = index;

                    var checked = $glyph.selectedIndex === index;
                    $input[checked ? 'setAttribute' : 'removeAttribute']('checked', 'checked');

                    var $label = $template.querySelector('label');
                    $label.id = id + '-label';
                    $label.className = 'fa fa-' + value;
                    $label.setAttribute('for', id);
                    $label.setAttribute('title', $option.text);
                }).querySelector('li');

                $list.appendChild($node);

                glyphLog.push({
                    id: id,
                    value: value
                });
            })($$options[i], i);
        }

    }).querySelector('#glyph-selector');

    $glyphSelector.querySelector('.header').appendChild(makeCloseButton(closeGlyphSelector));
    $studio.appendChild($glyphSelector);

    $glyphSelector.addEventListener('change', function (event) {

        event.stopPropagation();
        var index = event.target.value;
        $glyph.selectedIndex = index;

        updateGlyph();
    });

    $glyphSelector.addEventListener('click', function (event) {
        if (event.target.nodeName.toLowerCase() !== 'label') {
            return;
        }

        event.stopPropagation();
        closeGlyphSelector();
    });

    $glyphSelector.addEventListener('keydown', function (event) {

        if (event.keyCode === 13) { // Enter
            if (event.target.name)
                $glyph.selectedIndex = event.target.value;
            return updateGlyph(closeGlyphSelector);
        }

        if (event.keyCode === 38 || event.keyCode === 40) { // Up / Down
            event.preventDefault();

            var $container = event.target.parentNode.parentNode;
            var itemSize = event.target.parentNode.offsetWidth;
            var containerSize = $container.offsetWidth;
            var rowCount = Math.floor(containerSize / itemSize);
            var currentIndex = parseInt(event.target.value);
            var newIndex = currentIndex;
            var altFinder;

            if (event.keyCode === 38) {
                // Move up a row
                newIndex = currentIndex - rowCount;
                altFinder = 'firstElementChild';
            } else {
                // Move down a row
                newIndex = currentIndex + rowCount;
                altFinder = 'lastElementChild';
            }

            var newItem = $container.querySelector('input[value="' + newIndex + '"]') ||
                $container[altFinder].querySelector('input');

            $glyph.selectedIndex = newItem.value;
            newItem.checked = true;
            newItem.focus();
            rasterize();
        }
    });

    $glyphSelector.addEventListener('focus', function (event) {
        if (event.target !== $glyphSelector)
            return;

        event.stopPropagation();
    }, true);

    $glyph.addEventListener('change', function (event) {
        var $selectorItem = document.getElementById('glyph-selector-item-' + this.value);
        if ($selectorItem) {
            $selectorItem.click();
        }
    });
}

/**
 *
 */
function openGlyphSelector() {
    if (!$glyphSelector)
        initGlyphSelector();

    $glyphSelector.classList.remove('hidden');

    if ($glyph.value)
        document.getElementById('glyph-selector-item-' + $glyph.value + '-label').focus();

    $glyphSelector.focus();
}

/**
 *
 */
function closeGlyphSelector() {
    if (!$glyphSelector)
        return;

    $glyphSelector.classList.add('hidden');
    $glyphSelectorButton.focus();
}

// ==[ Templates ]============================================================

/**
 *
 */
function getCurrentTemplate() {
    return $template.value;
}

/**
 *
 */
function updateTemplate(callback) {
    callback = cb(callback);

    var path = $template.dataset.path;
    var shape = getCurrentTemplate();

    loadSVG(path + '/' + shape + '.svg', function (err, $svg) {
        if (err)
            return showError(err);

        $badge = $svg;

        extractOptions();
        setCustomPalette($svg);
        updatePalette(function () {
            updateMask(callback);
        });
    });
}

// ==[ Palettes ]=============================================================

function Palette(colors) {
    this._colors = {};
    if (colors) {
        for (var color in colors) {
            if (colors.hasOwnProperty(color)) {
                this._colors[color] = Palette.parseColor(colors[color]);
            }
        }
    }
    if (!this._colors.hasOwnProperty('glyph'))
        this._colors['glyph'] = '#000000';
}

Palette.prototype.toNode = function (id) {
    var content = [];
    for (var color in this._colors) {
        if (this._colors.hasOwnProperty(color)) {
            content.push('.color-' + color + ' { fill: ' + this._colors[color] + '; }');
        }
    }

    var $node = document.createElement('style');
    $node.type = 'text/css';
    $node.id = id || 'palette';
    $node.textContent = content.join('\n');
    return $node;
}

Palette.prototype.colors = function () {
    return Object.keys(this._colors);
}

Palette.prototype.color = function (name) {
    return this._colors[name] || '#000';
}

Palette.parseColor = function (str) {
    // Should probably be a bit more robust about this!
    if (!/^#[a-f0-9]{3}$/i.test(str))
        return str.toLowerCase();
    return '#' + str.charAt(1) + str.charAt(1)
        + str.charAt(2) + str.charAt(2)
        + str.charAt(3) + str.charAt(3);
}

Palette.fromDataset = function (dataset) {
    var colors = {};
    for (var item in dataset) {
        if (/^color\w+/i.test(item)) {
            var color = item
                .replace(/^color(\w)/i, function (m, c) {
                    return c.toLowerCase();
                })
                .replace(/[A-Z]/, function (m) {
                    return '-' + m.toLowerCase();
                });
            colors[color] = dataset[item];
        }
    }
    return new Palette(colors);
}

Palette.fromSVG = function ($svg) {
    var colors = {};
    var $node = $svg.getElementById('palette');
    if (!$node || $node.nodeName !== 'style')
        return new Palette();

    var $stylesheet = document.createElement('style');
    $stylesheet.setAttribute('media', 'print');
    $stylesheet.appendChild(document.createTextNode($node.textContent));
    document.head.appendChild($stylesheet);
    var sheet = $stylesheet.sheet;
    document.head.removeChild($stylesheet);

    var rules = sheet.rules || sheet.cssRules;
    for (var i = 0, l = rules.length; i < l; i++) {
        var rule = rules[i];
        var selector = rule.selectorText;
        if (/^\.color-/.test(selector)) {
            var key = selector.replace(/^\.color-/, '');
            var value = rule.style.fill || '#000';
            colors[key] = value;
        }
    }

    return new Palette(colors);
}

/**
 *
 */
function initPalettes() {
    var $custom = document.createElement('option');
    $custom.disabled = true;
    $custom.value = 'custom';
    $custom.text = 'Custom';
    $custom.id = 'custom-color-option';
    $palette.options.add($custom);

    var $container = document.getElementById('custom-palette');

    $palette.addEventListener('change', function () {
        var isCustom = (this.options[this.selectedIndex] === $custom);
        $custom.disabled = !isCustom;

        setCustomColors();
        updatePalette();
    });

    var changeTimer;

    $container.addEventListener('change', function (event) {
        var $input = event.target;
        $custom.setAttribute('data-color-' + $input.name, $input.value);
        $custom.disabled = false;
        $palette.selectedIndex = $palette.options.length - 1;

        updatePalette();
    });

    setCustomColors();
}

/**
 *
 */
function getCurrentPalette() {
    var $option = $palette.options[$palette.selectedIndex];
    return Palette.fromDataset($option.dataset);
}

/**
 *
 */
function updatePalette(callback) {
    callback = cb(callback);

    var $oldPalette = $badge.getElementById('palette');
    var $newPalette = getCurrentPalette().toNode();

    if ($oldPalette) {
        $oldPalette.parentNode.insertBefore($newPalette, $oldPalette);
        $oldPalette.parentNode.removeChild($oldPalette);
    } else {
        var $defs = $badge.querySelector('defs') || document.createElement('defs');

        if (!$defs.parentNode)
            $badge.insertBefore($defs, $badge.childNodes[0]);

        $defs.appendChild($newPalette)
    }

    updateGlyph(callback);
}

/**
 *
 */
function setCustomPalette($svg, callback) {
    callback = cb(callback);

    var colors = Palette.fromSVG($svg).colors();

    var $container = document.getElementById('custom-palette');
    var display = $container.style.display;
    $container.innerHTML = '';
    $container.style.display = 'none';
    $container.className = 'item';

    for (var i = 0, l = colors.length; i < l; i++) {
        var name = colors[i];
        var label = name.replace(/(^|-)(\w)/g, function (m, x, c) {
            return (x ? ' ' : '') + c.toUpperCase();
        });

        $container.appendChild(importTemplate('custom-color', function ($template) {
            var $label = $template.querySelector('span');
            $label.textContent = label;
            var $input = $template.querySelector('input');
            $input.name = name;
            $input.id = 'custom-color-picker-' + name;
        }));
    }

    if (colors.length)
        $container.style.display = display;

    setCustomColors();
}

/**
 *
 */
function setCustomColors() {
    var $custom = document.getElementById('custom-color-option');
    var $option = $palette.options[$palette.selectedIndex];
    var palette = Palette.fromDataset($option.dataset);
    var colors = palette.colors();

    for (var i = 0, l = colors.length; i < l; i++) {
        var colorName = colors[i];
        var colorValue = palette.color(colorName);
        $custom.setAttribute('data-color-' + colorName, colorValue);
        var $input = document.getElementById('custom-color-picker-' + colorName);
        if ($input) {
            $input.value = colorValue;
        }
    }
}

// ==[ Masks ]================================================================

function getCurrentMask() {
    return $mask.value;
}

/**
 *
 */
function updateMask(callback) {
    callback = cb(callback);

    var path = $mask.dataset.path;
    var mask = getCurrentMask();

    if (!mask) {
        var $svg = document.createElementNS(SVG_NS, 'svg');
        var $g = document.createElementNS(SVG_NS, 'g');
        $g.id = 'mask';
        $svg.appendChild($g);
        return done(null, $svg);
    }

    loadSVG(path + '/' + mask + '.svg', done);

    function done(err, $svg) {
        if (err)
            return showError(err);

        var $oldMask = $badge.querySelector('#mask');
        var $newMask = $svg.querySelector('#mask');

        $oldMask.parentNode.insertBefore($newMask, $oldMask);
        $oldMask.parentNode.removeChild($oldMask);

        rasterize(callback);
    }
}

// ==[ Options ]==============================================================

/**
 *
 */
function initOptions() {
    if ($badge)
        extractOptions();

    var $options = document.getElementById('options');
    $options.addEventListener('change', function (event) {
        event.stopPropagation();
        var option = event.target.name;
        if (!options.hasOwnProperty(option))
            return;

        options[option] = !!event.target.checked;
        setOptions();
    });
}

/**
 *
 */
function extractOptions() {
    var $options = document.getElementById('options');
    $options.innerHTML = '';

    var $optional = $badge.querySelectorAll('.optional');

    if (!$optional.length) {
        $options.innerHTML = '<i>None</l>';
        return;
    }

    for (var i = 0, l = $optional.length; i < l; i++) {
        var $option = $optional[i];
        var label = $option.getAttribute('title');
        var name = $option.id;
        var enabled = ($option.getAttribute('display') !== 'none');
        if (!options.hasOwnProperty(name))
            options[name] = enabled;

        $option[!!options[name] ? 'removeAttribute' : 'setAttribute']('display', 'none');

        $options.appendChild(importTemplate('option', function ($template) {
            var $checkbox = $template.querySelector('input');
            $checkbox.name = name;
            $checkbox.checked = !!options[name];

            var $label = $template.querySelector('span');
            $label.textContent = label;
        }));
    }
}

/**
 *
 */
function setOptions(callback) {
    callback = cb(callback);

    if (!$badge)
        return callback();

    for (var option in options) {
        if (options.hasOwnProperty(option)) {
            var $node = $badge.getElementById(option);
            var visible = !!options[option];
            $node && ($node[visible ? 'removeAttribute' : 'setAttribute']('display', 'none'));
        }
    }

    rasterize(callback)
}

// ==[ Glyphs ]===============================================================

/**
 *
 */
function getCurrentGlyph() {
    return $glyph.value;
}

/**
 *
 */
function getCurrentGlyphValue() {
    if (!$glyph.value)
        return '';

    var $i = document.createElement('i');
    $i.className = 'fa fa-' + getCurrentGlyph();
    document.body.appendChild($i);
    var chr = window.getComputedStyle($i, ':before').content;
    document.body.removeChild($i);

    chr = chr.replace(/["']/g, '');
    return chr;
}

/**
 *
 */
function updateGlyph(callback) {
    var glyph = getCurrentGlyphValue();

    if (!glyph)
        return setGlyphImage(null, callback);

    var $canvas = document.createElement('canvas');
    $canvas.width = parseInt($badgeRaster.offsetWidth);
    $canvas.height = parseInt($badgeRaster.offsetHeight);

    var ctx = $canvas.getContext('2d');
    ctx.font = parseInt($canvas.width / 3) + "px FontAwesome";
    ctx.fillStyle = getCurrentPalette().color('glyph');
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.shadowColor = "rgba(0,0,0,0.5)";
    ctx.shadowOffsetX = 0;
    ctx.shadowOffsetY = 0;
    ctx.shadowBlur = 5;

    ctx.fillText(glyph, $canvas.width / 2, $canvas.height / 2);

    var $image = new Image();
    $image.onload = function () {
        setGlyphImage($image, callback);
    }
    $image.src = $canvas.toDataURL("image/png");
    // $image.src = "./media/images/cheese.jpg";
}

/**
 *
 */
function setGlyphImage($image, callback) {
    callback = cb(callback);

    var $newGlyph = document.createElementNS(SVG_NS, 'g');
    $newGlyph.id = 'glyph';

    if (!$image)
        return done();

    var gxyAdd = 0;
    var whAdd = 0;


    if (window.size == 'big') {
        gxyAdd = 40;
        whAdd = 80
    } else if (window.size == 'small') {
        gxyAdd = -40;
        whAdd = -80
    }

    var iWidth = $image.width;
    var iHeight = $image.height;

    var rWidth = $badgeRaster.width;
    var rHeight = $badgeRaster.height;

    var box = $badge.getAttribute('viewBox').split(' ');

    var bWidth = parseInt(box[2]);
    var bHeight = parseInt(box[3]);

    var cx = bWidth / 2 + parseInt(box[0]);
    var cy = bHeight / 2 + parseInt(box[1]);

    var gWidth = iWidth / (rWidth / bWidth);
    var gHeight = iHeight / (rHeight / bHeight);
    var gx = cx - (gWidth / 2);
    var gy = cy - (gHeight / 2);

    var $glyph = document.createElementNS(SVG_NS, 'image');
    $glyph.setAttribute('x', gx - gxyAdd);
    $glyph.setAttribute('y', gy - gxyAdd);
    $glyph.setAttribute('width', gWidth + whAdd);
    $glyph.setAttribute('height', gHeight + whAdd);
    $glyph.setAttribute('xlink:href', $image.src);
    $newGlyph.appendChild($glyph);

    done();

    function done() {
        var $oldGlyph = $badge.getElementById('glyph');

        $oldGlyph.parentNode.insertBefore($newGlyph, $oldGlyph);
        $oldGlyph.parentNode.removeChild($oldGlyph);

        rasterize(callback);
    }
}

// ==[ Helpers ]==============================================================

/**
 *
 */
function rasterize(callback) {

    callback = cb(callback);

    var $svg = $badge.cloneNode(true);

    var $canvas = document.createElement('canvas');
    $canvas.width = parseInt($svg.getAttribute('width'));
    $canvas.height = parseInt($svg.getAttribute('height'));

    var ctx = $canvas.getContext('2d');
    var svg_xml = (new XMLSerializer()).serializeToString($svg);

    /*
     // This is the 'official' way of doing this. However, Firefox seems to have
     // an issue referencing relative fragment URIs created by `createObjectURL`.
     // So we're using a base64 encoding hack instead :( Worth noting that if
     // there are non-standard unicode characters in the XML, it'll die a death.

     var DOMURL = window.URL || window.webkitURL || window;
     var blob = new Blob([svg_xml], {type: 'image/svg+xml;charset=utf-8'});
     var url = DOMURL.createObjectURL(blob);
     */

    var url = 'data:image/svg+xml;base64,' + btoa(svg_xml);

    var $img = new Image();

    $img.onload = function () {
        ctx.drawImage($img, 0, 0);
        $badgeRaster.src = $canvas.toDataURL("image/png");
        callback();
    }

    $img.src = url;
}

/**
 *
 */
function cb(fn) {
    if (typeof fn === 'function')
        return fn;
    return function () {
    };
}

/**
 *
 */
function load(url, method, callback) {
    var request = new XMLHttpRequest();

    request.onload = function () {
        callback(null, request.responseXML || request.responseText, request);
    }

    request.onerror = function (err) {
        callback(err, null, request);
    }

    request.open(method, url, true);
    request.send();
}

/**
 *
 */
function loadSVG(path, callback) {
    if (svgCache[path])
        return callback(null, svgCache[path].cloneNode(true));

    load(path, 'GET', function (err, $doc, request) {
        if (err)
            return callback(err);

        if (!$doc || typeof $doc === 'string')
            return callback(new Error('Not valid SVG'));

        svgCache[path] = $doc.getElementsByTagName('svg')[0];
        callback(null, svgCache[path].cloneNode(true));
    })
}

/**
 *
 */
function importTemplate(name, builder) {
    var $template = document.getElementById(name + '-template');
    if (typeof builder === 'function')
        builder($template.content);
    return document.importNode($template.content, true);
}

/**
 *
 */
function makeCloseButton(callback) {
    var $template = importTemplate('close-button');
    $template.querySelector('button').addEventListener('click', callback);
    return $template;
}


Zerion Mini Shell 1.0