Tuesday, May 29, 2018

Accent folding for auto-complete

// Based on code from https://github.com/aristus/accent-folding
//
// Usage: accent_folded_hilite("Fulanilo López", 'lo')
//        --> "Fulanilo pez"

var accent_map = { 'ẚ': 'a', 'Á': 'a', 'á': 'a', 'À': 'a', 'à': 'a', 'Ă': 'a', 'ă': 'a', 'Ắ': 'a', 'ắ': 'a', 'Ằ': 'a', 'ằ': 'a', 'Ẵ': 'a', 'ẵ': 'a', 'Ẳ': 'a', 'ẳ': 'a', 'Â': 'a', 'â': 'a', 'Ấ': 'a', 'ấ': 'a', 'Ầ': 'a', 'ầ': 'a', 'Ẫ': 'a', 'ẫ': 'a', 'Ẩ': 'a', 'ẩ': 'a', 'Ǎ': 'a', 'ǎ': 'a', 'Å': 'a', 'å': 'a', 'Ǻ': 'a', 'ǻ': 'a', 'Ä': 'a', 'ä': 'a', 'Ǟ': 'a', 'ǟ': 'a', 'Ã': 'a', 'ã': 'a', 'Ȧ': 'a', 'ȧ': 'a', 'Ǡ': 'a', 'ǡ': 'a', 'Ą': 'a', 'ą': 'a', 'Ā': 'a', 'ā': 'a', 'Ả': 'a', 'ả': 'a', 'Ȁ': 'a', 'ȁ': 'a', 'Ȃ': 'a', 'ȃ': 'a', 'Ạ': 'a', 'ạ': 'a', 'Ặ': 'a', 'ặ': 'a', 'Ậ': 'a', 'ậ': 'a', 'Ḁ': 'a', 'ḁ': 'a', 'Ⱥ': 'a', 'ⱥ': 'a', 'Ǽ': 'a', 'ǽ': 'a', 'Ǣ': 'a', 'ǣ': 'a', 'Ḃ': 'b', 'ḃ': 'b', 'Ḅ': 'b', 'ḅ': 'b', 'Ḇ': 'b', 'ḇ': 'b', 'Ƀ': 'b', 'ƀ': 'b', 'ᵬ': 'b', 'Ɓ': 'b', 'ɓ': 'b', 'Ƃ': 'b', 'ƃ': 'b', 'Ć': 'c', 'ć': 'c', 'Ĉ': 'c', 'ĉ': 'c', 'Č': 'c', 'č': 'c', 'Ċ': 'c', 'ċ': 'c', 'Ç': 'c', 'ç': 'c', 'Ḉ': 'c', 'ḉ': 'c', 'Ȼ': 'c', 'ȼ': 'c', 'Ƈ': 'c', 'ƈ': 'c', 'ɕ': 'c', 'Ď': 'd', 'ď': 'd', 'Ḋ': 'd', 'ḋ': 'd', 'Ḑ': 'd', 'ḑ': 'd', 'Ḍ': 'd', 'ḍ': 'd', 'Ḓ': 'd', 'ḓ': 'd', 'Ḏ': 'd', 'ḏ': 'd', 'Đ': 'd', 'đ': 'd', 'ᵭ': 'd', 'Ɖ': 'd', 'ɖ': 'd', 'Ɗ': 'd', 'ɗ': 'd', 'Ƌ': 'd', 'ƌ': 'd', 'ȡ': 'd', 'ð': 'd', 'É': 'e', 'Ə': 'e', 'Ǝ': 'e', 'ǝ': 'e', 'é': 'e', 'È': 'e', 'è': 'e', 'Ĕ': 'e', 'ĕ': 'e', 'Ê': 'e', 'ê': 'e', 'Ế': 'e', 'ế': 'e', 'Ề': 'e', 'ề': 'e', 'Ễ': 'e', 'ễ': 'e', 'Ể': 'e', 'ể': 'e', 'Ě': 'e', 'ě': 'e', 'Ë': 'e', 'ë': 'e', 'Ẽ': 'e', 'ẽ': 'e', 'Ė': 'e', 'ė': 'e', 'Ȩ': 'e', 'ȩ': 'e', 'Ḝ': 'e', 'ḝ': 'e', 'Ę': 'e', 'ę': 'e', 'Ē': 'e', 'ē': 'e', 'Ḗ': 'e', 'ḗ': 'e', 'Ḕ': 'e', 'ḕ': 'e', 'Ẻ': 'e', 'ẻ': 'e', 'Ȅ': 'e', 'ȅ': 'e', 'Ȇ': 'e', 'ȇ': 'e', 'Ẹ': 'e', 'ẹ': 'e', 'Ệ': 'e', 'ệ': 'e', 'Ḙ': 'e', 'ḙ': 'e', 'Ḛ': 'e', 'ḛ': 'e', 'Ɇ': 'e', 'ɇ': 'e', 'ɚ': 'e', 'ɝ': 'e', 'Ḟ': 'f', 'ḟ': 'f', 'ᵮ': 'f', 'Ƒ': 'f', 'ƒ': 'f', 'Ǵ': 'g', 'ǵ': 'g', 'Ğ': 'g', 'ğ': 'g', 'Ĝ': 'g', 'ĝ': 'g', 'Ǧ': 'g', 'ǧ': 'g', 'Ġ': 'g', 'ġ': 'g', 'Ģ': 'g', 'ģ': 'g', 'Ḡ': 'g', 'ḡ': 'g', 'Ǥ': 'g', 'ǥ': 'g', 'Ɠ': 'g', 'ɠ': 'g', 'Ĥ': 'h', 'ĥ': 'h', 'Ȟ': 'h', 'ȟ': 'h', 'Ḧ': 'h', 'ḧ': 'h', 'Ḣ': 'h', 'ḣ': 'h', 'Ḩ': 'h', 'ḩ': 'h', 'Ḥ': 'h', 'ḥ': 'h', 'Ḫ': 'h', 'ḫ': 'h', 'H': 'h', '̱': 'h', 'ẖ': 'h', 'Ħ': 'h', 'ħ': 'h', 'Ⱨ': 'h', 'ⱨ': 'h', 'Í': 'i', 'í': 'i', 'Ì': 'i', 'ì': 'i', 'Ĭ': 'i', 'ĭ': 'i', 'Î': 'i', 'î': 'i', 'Ǐ': 'i', 'ǐ': 'i', 'Ï': 'i', 'ï': 'i', 'Ḯ': 'i', 'ḯ': 'i', 'Ĩ': 'i', 'ĩ': 'i', 'İ': 'i', 'i': 'i', 'Į': 'i', 'į': 'i', 'Ī': 'i', 'ī': 'i', 'Ỉ': 'i', 'ỉ': 'i', 'Ȉ': 'i', 'ȉ': 'i', 'Ȋ': 'i', 'ȋ': 'i', 'Ị': 'i', 'ị': 'i', 'Ḭ': 'i', 'ḭ': 'i', 'I': 'i', 'ı': 'i', 'Ɨ': 'i', 'ɨ': 'i', 'Ĵ': 'j', 'ĵ': 'j', 'J': 'j', '̌': 'j', 'ǰ': 'j', 'ȷ': 'j', 'Ɉ': 'j', 'ɉ': 'j', 'ʝ': 'j', 'ɟ': 'j', 'ʄ': 'j', 'Ḱ': 'k', 'ḱ': 'k', 'Ǩ': 'k', 'ǩ': 'k', 'Ķ': 'k', 'ķ': 'k', 'Ḳ': 'k', 'ḳ': 'k', 'Ḵ': 'k', 'ḵ': 'k', 'Ƙ': 'k', 'ƙ': 'k', 'Ⱪ': 'k', 'ⱪ': 'k', 'Ĺ': 'a', 'ĺ': 'l', 'Ľ': 'l', 'ľ': 'l', 'Ļ': 'l', 'ļ': 'l', 'Ḷ': 'l', 'ḷ': 'l', 'Ḹ': 'l', 'ḹ': 'l', 'Ḽ': 'l', 'ḽ': 'l', 'Ḻ': 'l', 'ḻ': 'l', 'Ł': 'l', 'ł': 'l', 'Ł': 'l', '̣': 'l', 'ł': 'l', '̣': 'l', 'Ŀ': 'l', 'ŀ': 'l', 'Ƚ': 'l', 'ƚ': 'l', 'Ⱡ': 'l', 'ⱡ': 'l', 'Ɫ': 'l', 'ɫ': 'l', 'ɬ': 'l', 'ɭ': 'l', 'ȴ': 'l', 'Ḿ': 'm', 'ḿ': 'm', 'Ṁ': 'm', 'ṁ': 'm', 'Ṃ': 'm', 'ṃ': 'm', 'ɱ': 'm', 'Ń': 'n', 'ń': 'n', 'Ǹ': 'n', 'ǹ': 'n', 'Ň': 'n', 'ň': 'n', 'Ñ': 'n', 'ñ': 'n', 'Ṅ': 'n', 'ṅ': 'n', 'Ņ': 'n', 'ņ': 'n', 'Ṇ': 'n', 'ṇ': 'n', 'Ṋ': 'n', 'ṋ': 'n', 'Ṉ': 'n', 'ṉ': 'n', 'Ɲ': 'n', 'ɲ': 'n', 'Ƞ': 'n', 'ƞ': 'n', 'ɳ': 'n', 'ȵ': 'n', 'N': 'n', '̈': 'n', 'n': 'n', '̈': 'n', 'Ó': 'o', 'ó': 'o', 'Ò': 'o', 'ò': 'o', 'Ŏ': 'o', 'ŏ': 'o', 'Ô': 'o', 'ô': 'o', 'Ố': 'o', 'ố': 'o', 'Ồ': 'o', 'ồ': 'o', 'Ỗ': 'o', 'ỗ': 'o', 'Ổ': 'o', 'ổ': 'o', 'Ǒ': 'o', 'ǒ': 'o', 'Ö': 'o', 'ö': 'o', 'Ȫ': 'o', 'ȫ': 'o', 'Ő': 'o', 'ő': 'o', 'Õ': 'o', 'õ': 'o', 'Ṍ': 'o', 'ṍ': 'o', 'Ṏ': 'o', 'ṏ': 'o', 'Ȭ': 'o', 'ȭ': 'o', 'Ȯ': 'o', 'ȯ': 'o', 'Ȱ': 'o', 'ȱ': 'o', 'Ø': 'o', 'ø': 'o', 'Ǿ': 'o', 'ǿ': 'o', 'Ǫ': 'o', 'ǫ': 'o', 'Ǭ': 'o', 'ǭ': 'o', 'Ō': 'o', 'ō': 'o', 'Ṓ': 'o', 'ṓ': 'o', 'Ṑ': 'o', 'ṑ': 'o', 'Ỏ': 'o', 'ỏ': 'o', 'Ȍ': 'o', 'ȍ': 'o', 'Ȏ': 'o', 'ȏ': 'o', 'Ơ': 'o', 'ơ': 'o', 'Ớ': 'o', 'ớ': 'o', 'Ờ': 'o', 'ờ': 'o', 'Ỡ': 'o', 'ỡ': 'o', 'Ở': 'o', 'ở': 'o', 'Ợ': 'o', 'ợ': 'o', 'Ọ': 'o', 'ọ': 'o', 'Ộ': 'o', 'ộ': 'o', 'Ɵ': 'o', 'ɵ': 'o', 'Ṕ': 'p', 'ṕ': 'p', 'Ṗ': 'p', 'ṗ': 'p', 'Ᵽ': 'p', 'Ƥ': 'p', 'ƥ': 'p', 'P': 'p', '̃': 'p', 'p': 'p', '̃': 'p', 'ʠ': 'q', 'Ɋ': 'q', 'ɋ': 'q', 'Ŕ': 'r', 'ŕ': 'r', 'Ř': 'r', 'ř': 'r', 'Ṙ': 'r', 'ṙ': 'r', 'Ŗ': 'r', 'ŗ': 'r', 'Ȑ': 'r', 'ȑ': 'r', 'Ȓ': 'r', 'ȓ': 'r', 'Ṛ': 'r', 'ṛ': 'r', 'Ṝ': 'r', 'ṝ': 'r', 'Ṟ': 'r', 'ṟ': 'r', 'Ɍ': 'r', 'ɍ': 'r', 'ᵲ': 'r', 'ɼ': 'r', 'Ɽ': 'r', 'ɽ': 'r', 'ɾ': 'r', 'ᵳ': 'r', 'ß': 's', 'Ś': 's', 'ś': 's', 'Ṥ': 's', 'ṥ': 's', 'Ŝ': 's', 'ŝ': 's', 'Š': 's', 'š': 's', 'Ṧ': 's', 'ṧ': 's', 'Ṡ': 's', 'ṡ': 's', 'ẛ': 's', 'Ş': 's', 'ş': 's', 'Ṣ': 's', 'ṣ': 's', 'Ṩ': 's', 'ṩ': 's', 'Ș': 's', 'ș': 's', 'ʂ': 's', 'S': 's', '̩': 's', 's': 's', '̩': 's', 'Þ': 't', 'þ': 't', 'Ť': 't', 'ť': 't', 'T': 't', '̈': 't', 'ẗ': 't', 'Ṫ': 't', 'ṫ': 't', 'Ţ': 't', 'ţ': 't', 'Ṭ': 't', 'ṭ': 't', 'Ț': 't', 'ț': 't', 'Ṱ': 't', 'ṱ': 't', 'Ṯ': 't', 'ṯ': 't', 'Ŧ': 't', 'ŧ': 't', 'Ⱦ': 't', 'ⱦ': 't', 'ᵵ': 't', 'ƫ': 't', 'Ƭ': 't', 'ƭ': 't', 'Ʈ': 't', 'ʈ': 't', 'ȶ': 't', 'Ú': 'u', 'ú': 'u', 'Ù': 'u', 'ù': 'u', 'Ŭ': 'u', 'ŭ': 'u', 'Û': 'u', 'û': 'u', 'Ǔ': 'u', 'ǔ': 'u', 'Ů': 'u', 'ů': 'u', 'Ü': 'u', 'ü': 'u', 'Ǘ': 'u', 'ǘ': 'u', 'Ǜ': 'u', 'ǜ': 'u', 'Ǚ': 'u', 'ǚ': 'u', 'Ǖ': 'u', 'ǖ': 'u', 'Ű': 'u', 'ű': 'u', 'Ũ': 'u', 'ũ': 'u', 'Ṹ': 'u', 'ṹ': 'u', 'Ų': 'u', 'ų': 'u', 'Ū': 'u', 'ū': 'u', 'Ṻ': 'u', 'ṻ': 'u', 'Ủ': 'u', 'ủ': 'u', 'Ȕ': 'u', 'ȕ': 'u', 'Ȗ': 'u', 'ȗ': 'u', 'Ư': 'u', 'ư': 'u', 'Ứ': 'u', 'ứ': 'u', 'Ừ': 'u', 'ừ': 'u', 'Ữ': 'u', 'ữ': 'u', 'Ử': 'u', 'ử': 'u', 'Ự': 'u', 'ự': 'u', 'Ụ': 'u', 'ụ': 'u', 'Ṳ': 'u', 'ṳ': 'u', 'Ṷ': 'u', 'ṷ': 'u', 'Ṵ': 'u', 'ṵ': 'u', 'Ʉ': 'u', 'ʉ': 'u', 'Ṽ': 'v', 'ṽ': 'v', 'Ṿ': 'v', 'ṿ': 'v', 'Ʋ': 'v', 'ʋ': 'v', 'Ẃ': 'w', 'ẃ': 'w', 'Ẁ': 'w', 'ẁ': 'w', 'Ŵ': 'w', 'ŵ': 'w', 'W': 'w', '̊': 'w', 'ẘ': 'w', 'Ẅ': 'w', 'ẅ': 'w', 'Ẇ': 'w', 'ẇ': 'w', 'Ẉ': 'w', 'ẉ': 'w', 'Ẍ': 'x', 'ẍ': 'x', 'Ẋ': 'x', 'ẋ': 'x', 'Ý': 'y', 'ý': 'y', 'Ỳ': 'y', 'ỳ': 'y', 'Ŷ': 'y', 'ŷ': 'y', 'Y': 'y', '̊': 'y', 'ẙ': 'y', 'Ÿ': 'y', 'ÿ': 'y', 'Ỹ': 'y', 'ỹ': 'y', 'Ẏ': 'y', 'ẏ': 'y', 'Ȳ': 'y', 'ȳ': 'y', 'Ỷ': 'y', 'ỷ': 'y', 'Ỵ': 'y', 'ỵ': 'y', 'ʏ': 'y', 'Ɏ': 'y', 'ɏ': 'y', 'Ƴ': 'y', 'ƴ': 'y', 'Ź': 'z', 'ź': 'z', 'Ẑ': 'z', 'ẑ': 'z', 'Ž': 'z', 'ž': 'z', 'Ż': 'z', 'ż': 'z', 'Ẓ': 'z', 'ẓ': 'z', 'Ẕ': 'z', 'ẕ': 'z', 'Ƶ': 'z', 'ƶ': 'z', 'Ȥ': 'z', 'ȥ': 'z', 'ʐ': 'z', 'ʑ': 'z', 'Ⱬ': 'z', 'ⱬ': 'z', 'Ǯ': 'z', 'ǯ': 'z', 'ƺ': 'z', '2': '2', '6': '6', 'B': 'B', 'F': 'F', 'J': 'J', 'N': 'N', 'R': 'R', 'V': 'V', 'Z': 'Z', 'b': 'b', 'f': 'f', 'j': 'j', 'n': 'n', 'r': 'r', 'v': 'v', 'z': 'z', '1': '1', '5': '5', '9': '9', 'A': 'A', 'E': 'E', 'I': 'I', 'M': 'M', 'Q': 'Q', 'U': 'U', 'Y': 'Y', 'a': 'a', 'e': 'e', 'i': 'i', 'm': 'm', 'q': 'q', 'u': 'u', 'y': 'y', '0': '0', '4': '4', '8': '8', 'D': 'D', 'H': 'H', 'L': 'L', 'P': 'P', 'T': 'T', 'X': 'X', 'd': 'd', 'h': 'h', 'l': 'l', 'p': 'p', 't': 't', 'x': 'x', '3': '3', '7': '7', 'C': 'C', 'G': 'G', 'K': 'K', 'O': 'O', 'S': 'S', 'W': 'W', 'c': 'c', 'g': 'g', 'k': 'k', 'o': 'o', 's': 's', 'w': 'w' };

function accent_fold(s) {
    if (!s) { return ''; }
    var ret = '';
    for (var i = 0, len = s.length; i < len; i++) {
        ret += accent_map[s[i]] || s[i];
    }
    return ret;
}

function accent_folded_hilite(str, q) {
    var str_folded = accent_fold(str).toLowerCase().replace(/[<>]+/g, ''),
        q_folded = accent_fold(q).toLowerCase().replace(/[<>]+/g, ''),
  re = new RegExp(q_folded, 'g'),
        hilite_hints = str_folded.replace(re, '<' + q_folded + '>'),
  highlighted = '';
    for (var i = 0, len = hilite_hints.length, c = '', h = '', spos = 0; i < len; i++) {
        c = str[spos];
        h = hilite_hints[i];
        highlighted += (h === '<') ? '' : (h === '>') ? '' : (spos += 1, c);
    }
    return highlighted;
}


Friday, January 5, 2018

ChartJS 2, Variable number of Bars

In the next Chart implementation there are several features worth knowing.

1) Hidden yAxes line
2) Two line xAxes (Array)
3) Variable width depending on the number of visible bars.

Monday, December 18, 2017

Canvas based bar graphics

ChartJS 2 is an open source highly customizable Graphics Library for JavaScript.
Here I include an example to achieve this bar chart:


HTML;

<div class="jsBarGraphDiv" data-bardata="95,50,95,50,50,10" data-colors="#F44133,#FFC300,#4BB04F" 
   data-labels="Jul,Ago,Set,Out,Nov,Dec">
  <canvas height="215" id="barCanvas"></canvas>
</div>

JavaScript:

Just instance this class:

function BarChart(pSettings) {
    var data = {
        labels: [],
        datasets: [{
            type: 'bar',
            backgroundColor: [],
            data: []
        }]
    },
        config = {
            type: 'bar',
            data: {},
            options: {
                responsive: true,
                maintainAspectRatio: false,
                legend: {
                    display: false
                },
                title: {
                    display: false,
                },
                tooltips:
                {
                    enabled: false
                },
                scales: {
                    xAxes: [{
                        barThickness: 14,
                        gridLines: {
                            display: false
                        },
                        ticks: {
                            maxRotation: 0
                        }
                    }],
                    yAxes: [{
                        scaleLabel: {
                            display: true,
       labelString: 'Baixo         Médio         Alto'
                        },
                        gridLines: {
                            drawTicks: true
                        },
                        ticks: {
                            beginAtZero: true,
                            min: 0,
                            max: 100,
                            stepSize: 34,
                            callback: function () {
                                return '';
                            }
                        }
                    }]
                }
            }
        },
        settings = {
            BarGraphDiv: '.jsBarGraphDiv'
        },
        options = {},
            aColors = [];
    //
    function init(pSettings) {
        options = $.extend(settings, pSettings || {});
        var _$BarGraphDiv = $(options.BarGraphDiv),
            _graphData = _$BarGraphDiv.data('bardata');
        if (_graphData) {
            if (typeof _graphData == 'number') {
                _graphData = [_graphData];
                data.labels = [_$BarGraphDiv.data('labels')];
            }
            else {
                _graphData = _graphData.split(',');
                _graphData = _graphData.map(function (el) { return Number(el) });
                data.labels = _$BarGraphDiv.data('labels').split(',');
            }
            aColors = _$BarGraphDiv.data('colors').split(',');            
            data.datasets[0].backgroundColor = _graphData.map(function (el, i) {
                return aColors[Math.floor(el / 33.4)];
            });
            data.datasets[0].data = _graphData;
            config.data = data;
            var ctx = $(options.BarGraphDiv).find('canvas')[0].getContext('2d');
            new Chart(ctx, config);
            var _cssLowMidHigh = ['low', 'mid', 'high'][Math.floor(_graphData[_graphData.length - 1] / 33.4)];
            _$BarGraphDiv.addClass(_cssLowMidHigh);
        }
    }
    //
    init(pSettings);
}

Thursday, October 5, 2017

Animated scroll to a certain point of the web page.

Just add the next code:

$('html,body').animate({ scrollTop: _top }, 1000, 'swing');

Reference: http://api.jquery.com/animate/

CLEditor, paste as plain text

CLEditor is an open source jQuery plug-in which provides a lightweight, full featured, cross browser, extensible, WYSIWYG HTML editor that can be easily added into any web site.

In order to prevent users to paste content with formatted text, and instead, get only its text the following chunk of cross-browser code:


var _$ta = $('textarea.richText').cleditor({ 
            // options
           }),
    _clEdit = _$ta.cleditor()[0];

$(_clEdit.$frame[0].contentWindow.document)
       .on('rightclick', function (e) {
             e.preventDefault();
       })
       .on('paste', function (e) { // Paste as plain text
           var content = '';
           e.preventDefault();
           if (e.originalEvent.clipboardData) {
               content = (e.originalEvent 
                   || e).clipboardData.getData('text/plain');
           }
           else if (window.clipboardData) {
               content = window.clipboardData.getData('Text');
           }
           content = content.replace(/\n/g, "<br />");
           _clEdit.execCommand('inserthtml', content);
        });

Wednesday, September 27, 2017

Get int or float number from a string

Number("this a test (12.75%)".match(/\d*\.*\d+/g)[0]); // Output: 12.75

Tuesday, October 25, 2016

Sort DOM elements by jQuery

HTML:

<ul class="alphaList">
  <li>apples</li>
  <li>cats</li>
  <li>bears</li>
</ul>


JavaScript/jQuery:

var elems = $('.alphalist li').detach().sort(function (a, b) {
  return ($(a).text() < $(b).text() ? -1
        : $(a).text() > $(b).text() ? 1 : 0);
   });
$('.alphalist').append(elems);


Note: jQuery detach() gets (removing) elements from DOM.

Thursday, March 10, 2016

jQuery Custom Events

Custom events allow data interchange between different modules or classes running in the current page.
These events are delivered as a broadcast. They are invoked with a "trigger" method, and catched with the "on" method.
Parameters are optional. If there are more than one, these have to be embedded in an array, yet the target methods must declare those parameters individually.

Wednesday, October 28, 2015

Extracts a word which starts with a given substring

// extracts js_* class
$(anySelector).attr('class').match(/\bjs_[^\b]*?\b/)[0]; 

Wednesday, June 17, 2015

Remove duplicates in an array


[1,1,2,2,3,3,4].reduce(function (a,b) { if (a.indexOf(b) < 0) a.push(b); return a;},[]);

will return [1,2,3,4]

In case of arrays composed of JSON objects use this expression for the "if"clause:

(JSON.stringify(a).indexOf(JSON.stringify(b))

Tuesday, May 12, 2015

Brackground-color transitions

With a tiny jQuery plugin and CSS3 is possible to create programmatic background color transitions.

See this page for "easing" possible values.

Thursday, April 2, 2015

Filter a list with Highlight

For this user filtered I've used two tiny jQuery plugins to keep in mind.

The first is called "MyCaseInsensitiveContains" (by Eric Best. Found in stackoverflow.com) which does the same as jQuery built-in ":contains" but not case sensitive.

The second plugin ("highlight", by Bartek Szopka) allows to highlight texts, wrapping them in a span with ".highlight" CSS class.

Note: This post uses different techniques used in the post "Filter list by typed text".
 

Thursday, March 26, 2015

PURE - Javascript Template Engine

Write your templates in pure HTML

Clean of any inline logic or special tags
CSS selectors are used to bridge the HTML with Javascript actions
Providing a radical separation between the representation and the logicHere we explain why we did PURE back in 2008
And you can ask your questions to the user group

Download pure.js on Github

Where to use PURE?

PURE can be used where Javascript and DOM are available
It can be run server side, but shines client side

If a Javascript library is present in the page( jQuery, dojo, domassistant, mootools, prototype, sizzle or sly )

PURE will automatically extend it with the methods described here: http://beebole.com/pure/

I've written myself a demo. Pay special attention to auxiliar function tmplHandle().

Wednesday, January 21, 2015

Bing Maps API

Bing Maps is a web service created by Microsoft Corporation which allows end users to search and view maps from any part of the world. It has an API with allows to embed Maps in web pages. This post is an starting point to develop Bing Maps.

In the website http://www.bingmapsportal.com/isdk/ajaxv7 there is all the information about this API and live examples. This library is highly configurable to adjust your website look requirements.

The JavaScript library to include is the following:
http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0
To create a map there are a couple of required elements: the target DIV of the map and a JSON with the Map settings. This JSON at least has to have a property called "credentials" with the developer/company credentials to use the library on any website. There are other properties that may be useful to setup the map. For example:

var mapOptions = {
      credentials: "your credentials",
      width: 490,
      height: 370,
      zoom: 10,
      showMapTypeSelector: false,
      disableBirdseye: true,
      enableSearchLogo: false
}

To create the map, and put it in a <div> with id="mapContentDiv" the code could be:

var _map = new Microsoft.Maps.Map(document.getElementById(mapContentDiv), mapOptions);

To set a pin on a map (also called "Pushpin") you must create a Pushpin object. Example:

var _mapCenter = new Microsoft.Maps.Location(47.5, -122.33), // Latitude, Longitude
    _pushpinOptions = { draggable: false }, // optional setting. Just as an example
    _pushpin = new Microsoft.Maps.Pushpin(_mapCenter, _pushpinOptions);

_map.entities.push(_pushpin); // To set it on the previously created map

You may include all the Pushpins you need.

There's a particularly interesting point at inserting several Pushpins not too far from each other and set a zoom level which permits to view them all. To do this, the code may be:

var _mapLocation1 = new Microsoft.Maps.Location(47.5, -122.33), 
    _mapLocation2 = new Microsoft.Maps.Location(47.51, -122.33);
    _pushpinOptions = { draggable: false }, // optional setting. Just as an example
    _pushpin = new Microsoft.Maps.Pushpin(_mapLocation1 , _pushpinOptions);
_map.entities.push(_pushpin); 
_pushpin = new Microsoft.Maps.Pushpin(_mapLocation2 , _pushpinOptions);
_map.entities.push(_pushpin); 

_map.setView({ bounds: Microsoft.Maps.LocationRect.fromLocations(_mapLocation1, _mapLocation2) }); // As many locations as needed

The next code produces a map like the one below.

var _mapLocation1 = new Microsoft.Maps.Location(47.5, -122.33),
      _mapLocation2 = new Microsoft.Maps.Location(47.51, -122.33),
      _pushpinOptions = { draggable: false },
      _pushpin = new Microsoft.Maps.Pushpin(_mapLocation1, _pushpinOptions);
 map.entities.push(_pushpin);
_pushpin = new Microsoft.Maps.Pushpin(_mapLocation2, _pushpinOptions);
 map.entities.push(_pushpin);

map.setView({ bounds: Microsoft.Maps.LocationRect.fromLocations(_mapLocation1 , _mapLocation2) });


For more information I encourage you to look up on the mentioned API website.

Wednesday, October 29, 2014

Code optimizations and new standards

Most of the times the use of some new standards of JavasScript, known as ECMAScript, is constraint by browser compatibility. The latest browsers along with IE from version 9 implement many or all of these new features. See ECMAScript 5 compatibility table.

This post is also about code optimization. One of the most important point to have in mind at coding in JavaScript is to avoid unnecessary repetitions to accelerate execution and save bytes of code.

Lets see some examples of these concepts. These functions do the same in different ways:

Not optimized code:
var retval = false;
if ((window.location.href.toLowerCase().indexOf('/candidate1/list.aspx') > -1) ||
    (window.location.href.toLowerCase().indexOf('/defaultcompany.aspx') > -1) ||
    (window.location.href.toLowerCase().indexOf('/defaultcompanyv2.aspx') > -1)) {
 retval = true;
}
return retval;

Optimized code with JavaScript:
var retval = false,
    _href = window.location.href.toLowerCase(), 
    _a = ['/candidate1/list.aspx','/defaultcompany.aspx','/defaultcompanyv2.aspx'];
for (var i = 0; !retval && i < _a.length; i++) retval = (-1 != _href.indexOf(_a[i]));
return retval;

Optimized code with jQuery:
var _href = window.location.href.toLowerCase();
return $.map(['/candidate1/list.aspx','/defaultcompany.aspx','/defaultcompanyv2.aspx'],function (e) { return _href.indexOf(e) != -1 ? 1 : null; }).length;

Optimized code with JavaScript (ECMAScript 5):
var _href = window.location.href.toLowerCase(), 
return ['/candidate1/list.aspx', '/defaultcompany.aspx', '/defaultcompanyv2.aspx'].some(function (e) {
  return -1 != _href.indexOf(e);
});

Thursday, September 25, 2014

Cross-browser Image preview

To preview an image in browser before uploading it to server.
Tested in HTML5 browsers and IE > 7.
JSFiddle issues an error in IE < 10 so I put the code in here.
jQuery is used in this example.

CSS:

.imgLogoIE
{
  filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale);
  width:500px;
  height:400px;
}

JavaScript:

var v = navigator.appVersion,
    p = v.indexOf('MSIE'),
    IElt10 = (p != -1 && parseFloat(v.substr(p+5)) < 10);

function LoadPreviewImg (pFile) {
    var _$imgLogo = $('.js_imgLogo');
    if (IElt10) {
        if ('IMG' == _$imgLogo.prop('nodeName')) {
             _$imgLogo.replaceWith('
');
        }
        setTimeout(function () {
            $('.js_imgLogo').get(0).filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = pFile.value
        },50);
    }
    else if (pFile.files && pFile.files[0]) {
            var _reader = new FileReader(); 
            _reader.onload = function (e) {
                _$imgLogo.attr('src', e.target.result);
            }
            _reader.onerror = function (e) {
                _$imgLogo.hide();
            }
            _reader.readAsDataURL(pFile.files[0]);
        }
}

HTML:

<form id="form1">
  preview:
        <input onchange="LoadPreviewImg(this)" type="file" />
        <img class="js_imgLogo" />
</form>

Tuesday, July 15, 2014

Class definitions for lesser code

In order to minimize the amount of code is preferable to use private attributes and methods (AA&MM). The next example shows how to do it in a simple way. You can see how to access either private or public AA&MM.

The accessibility boundary of variables in JavaScript starts from the point where they are declared to every function invoked from that point including callbacks and either setTimeout() or setInterval().

If you have to define an instantiable class you may use the definition of the dynamic class called MainClass in this example:

function MainClass () {
     // ------------------------------------ Private attributes & methods
     var me = this,
         privateVar = 1;
     function init() {
        bindEvents();
     }
     function bindEvents() {
        $('.aSelector').on('click', ClickOn_aSelector);
     }
     function ClickOn_aSelector(e) {
         e.preventDefault();
         privateFunc();
         me.publicMethod();
         // "me." allows to access public methods or attributes 
         //       from either private or public methods.
     }
     function privateFunc () {
       console.log(privateVar);
       console.log(me.publicAtt);
     }
     // ------------------------------------ Public attributes & methods
     this.publicAtt = 2;
     this.publicMethod = function () {
        var _myself = this;
        privateFunc();
        _myself.publicMethod2(3)
     };
     this.publicMethod2 = function (pNum) {
        console.log (privateVar + this.publicAtt + pNum); // 6
     };
     //
     init();
  };

var oMainClass = new MainClass();
oMainClass.publicMethod();

Thursday, February 20, 2014