Wednesday 29 May 2013

jQuery.log

To avoid checks if window.console is available:

/****************************************
* jQuery extensions
****************************************/
jQuery.extend({
    "log": window.console ? window.console : { _isStubObject: true }
});
if (!jQuery.log._init) {
    jQuery.log._init = function (logLevel) {
        if (!jQuery.log._logLevels) {
            jQuery.log._logLevels = {
                All: 0,
                Debug: 1,
                Info: 2,
                Warn: 3,
                Error: 4
            };
        }
        if (!logLevel) logLevel = jQuery.log._logLevels.All;

        if (!jQuery.log._unsupported_message) jQuery.log._unsupported_message = function (functionName) {
            if (window && window.console) {
                if (window.console.warn)
                    window.console.warn("console." + functionName + "() is not supported!");
                else if (window.console.log)
                    window.console.log("WARNING: console." + functionName + "() is not supported!");
            }
        };

        if (!jQuery.log.memory) jQuery.log.memory = { _isStubObject: true };
        if (!jQuery.log.memory.jsHeapSizeLimit) jQuery.log.memory.jsHeapSizeLimit = -1;
        if (!jQuery.log.memory.totalJSHeapSize) jQuery.log.memory.totalJSHeapSize = -1;
        if (!jQuery.log.memory.usedJSHeapSize) jQuery.log.memory.usedJSHeapSize = -1;

        if (!jQuery.log.assert) jQuery.log.assert = function () { jQuery.log._unsupported_message("assert"); };
        if (!jQuery.log.clear) jQuery.log.clear = function () { jQuery.log._unsupported_message("clear"); };
        if (!jQuery.log.count) jQuery.log.count = function () { jQuery.log._unsupported_message("count"); };
        if (!jQuery.log.debug) {
            jQuery.log._unsupported_message("debug");
            jQuery.log.debug = window.console.log;
        };
        if (!jQuery.log.dir) jQuery.log.dir = function () { jQuery.log._unsupported_message("dir"); };
        if (!jQuery.log.dirxml) jQuery.log.dirxml = function () { jQuery.log._unsupported_message("dirxml"); };
        if (!jQuery.log.error) {
            jQuery.log._unsupported_message("error");
            jQuery.log.error = window.console.log;
        };
        if (!jQuery.log.exception) jQuery.log.exception = function () { jQuery.log._unsupported_message("exception"); };
        if (!jQuery.log.group) jQuery.log.group = function () { jQuery.log._unsupported_message("group"); };
        if (!jQuery.log.groupCollapsed) jQuery.log.groupCollapsed = function () { jQuery.log._unsupported_message("groupCollapsed"); };
        if (!jQuery.log.groupEnd) jQuery.log.groupEnd = function () { jQuery.log._unsupported_message("groupEnd"); };
        if (!jQuery.log.info) {
            jQuery.log._unsupported_message("info");
            jQuery.log.info = window.console.log;
        };
        //if (!jQuery.log.log) jQuery.log.log = function () { jQuery.log._unsupported_message("log"); };
        if (!jQuery.log.markTimeline) jQuery.log.markTimeline = function () { jQuery.log._unsupported_message("markTimeline"); };
        if (!jQuery.log.profile) jQuery.log.profile = function () { jQuery.log._unsupported_message("profile"); };
        if (!jQuery.log.profileEnd) jQuery.log.profileEnd = function () { jQuery.log._unsupported_message("profileEnd"); };
        if (!jQuery.log.table) jQuery.log.table = function () { jQuery.log._unsupported_message("table"); };
        if (!jQuery.log.time) jQuery.log.time = function () { jQuery.log._unsupported_message("time"); };
        if (!jQuery.log.timeEnd) jQuery.log.timeEnd = function () { jQuery.log._unsupported_message("timeEnd"); };
        if (!jQuery.log.timeStamp) jQuery.log.timeStamp = function () { jQuery.log._unsupported_message("timeStamp"); };
        if (!jQuery.log.trace) jQuery.log.trace = function () { jQuery.log._unsupported_message("trace"); };
        if (!jQuery.log.warn) {
            jQuery.log._unsupported_message("warn");
            jQuery.log.warn = window.console.log;
        };

        jQuery.log.info("INFO: jQuery.log is initialized.");
    };
}
jQuery.log._init();

JavaScript - String Extensions #2 [ replaceAll() ]

Unfortunately function replace() in JavaScript replaces only the first matching SubString.
Here is an extension of String Type, which allows you to replace all the found SubStrings.
You can optionally specify more than one (array of strings) string to search for.
/****************************************
* String extensions
****************************************/
String.prototype.replaceAll = function (search, replace) {
    /// 
    /// Replaces all instances of [search] String or Array of Strings
    /// 

    var searches = [];
    if (Object.prototype.toString.call(search) === '[object Array]') {
        searches = search;
    } else {
        searches = [search];
    }
    var result = this + "";
    for (var i = 0; i < searches.length; i++) {
        result = result.split(searches[i]).join(replace);
    }

    return result;
};

Usage of simple replace:
var someString = "aaa-bbb-ccc-ddd";
var resultCsv = someString.replaceAll("-", ";");

Replace array of strings:
var someString = "aaa-bbb#ccc:ddd";
var resultCsv = someString.replaceAll(["-", "#", ":"], ";");

JavaScript - String Extensions #1 [ isEmpty(), left(), right(), contains(), repeat() ]

Often, when I am working with Strings in JavaScript, I need many common functions.
Such as the left(), right(), isEmpty(), contains(), ETC.
To make work easier, I wrote a few to appropriate extensions for String:
/****************************************
* String extensions
****************************************/
String.prototype.isEmpty = function () {
    /// 
    /// Check if string is empty
    /// 
    return (this.length === 0);
};

String.prototype.left = function (subStringLength) {
    /// 
    /// Gets left part of string
    /// 
    if (subStringLength > this.length) return this;
    return this.substring(0, subStringLength);
};

String.prototype.right = function (subStringLength) {
    /// 
    /// Gets right part of string
    /// 
    if (subStringLength > this.length) return this;
    return this.substring(this.length, this.length - subStringLength);
};

String.prototype.contains = function (subString) {
    /// 
    /// Checks if strin contains other string
    /// 
    if (this.indexOf(subString) > 0) return true;
    return false;
};

String.prototype.repeat = function (num) {
    /// 
    /// Repeates string [num]-times
    /// 
    if (isNaN(num)) return null;
    if (!(num > 0)) return "";
    return new Array(num + 1).join(this);
};

MSSQL - Convert list to table #1 (array of numbers in string form)

Extended version of function from this post: MSSQL - Convert list to table #2 (array of string items)
Function described here (TABLE-Value UDF) converts a string in the form "123;bbb;;;456" to tabular form.
Result will contain only non-empty items which was possible to convert to INTEGER.
In case if list has non-unique items, the function returns the serial number for each items group (RANK).

-- Drop Function if exists
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.fnArray2IntTable'))
    DROP FUNCTION dbo.fnArray2IntTable;
GO

/*=============================================
Author:
    Yuri Abele
Changes:
    11.06.2013 - Yuri Abele - initial
Description:
    Function to convert list of numeric Values to Table of integers
Remark:
    Empty and non-numeric values will be ignored

Usage: Get all items
    SELECT * FROM dbo.fnArray2IntTable(N';444;bbb;333;;;333;444;555;', N';');
Usage: Get all non-empty items and filter non-unique
    SELECT * FROM dbo.fnArray2IntTable(N';444;bbb;333;;;333;444;555;', N';') WHERE ItemRank=1;
=============================================*/
CREATE FUNCTION dbo.fnArray2IntTable(
    @Array NVARCHAR(MAX),
    @Delim NCHAR(1)
)
-- Container for Array Items
RETURNS @Data TABLE(
    ItemIndex INT IDENTITY(1,1),
    ItemValue INT,
    ItemRank INT
)
AS BEGIN
    -- Container for XML
    DECLARE
        @XmlText NVARCHAR(MAX),
        @Xml XML;
    
    -- Remove empty inner items
    WHILE (CHARINDEX(@Delim + @Delim, @Array, 0) > 0) BEGIN
        SET @Array = REPLACE(@Array, @Delim + @Delim, @Delim);
    END;
    -- Remove empty left item
    IF(LEFT(@Array, 1) = @Delim) BEGIN
        SET @Array = SUBSTRING(@Array, 2, LEN(@Array)-1)
    END;
    -- Remove empty right item
    IF(RIGHT(@Array, 1) = @Delim) BEGIN
        SET @Array = SUBSTRING(@Array, 1, LEN(@Array)-1)
    END;
    
    -- Prepare XML-Text
    SET @XmlText = N'<List><Item>' +
        REPLACE(@Array, @Delim, N'</Item><Item>') +
        N'</Item></List>';
    
    -- Convert Array to XML
    SET @Xml = CAST(@XmlText AS XML);
    
    -- Temp Table-Variableble
    DECLARE @TempData TABLE(
        ItemIndex INT IDENTITY(1,1),
        ItemValue NVARCHAR(MAX)
    )

    -- Extract Array Items to temp Table-Variable
    INSERT INTO @TempData
    SELECT
        Item = item.value('.', 'INT')
    FROM
        @Xml.nodes('//Item') XMLDATA(item)
    WHERE
        -- Skeep non-numeric items
        ISNUMERIC(item.value('.', 'NVARCHAR(MAX)')) = 1;
    
    -- Calculate Rank for each item (to find non-unique items)
    INSERT INTO @Data(ItemValue, ItemRank)
    SELECT
        ItemValue,
        ItemRank=RANK() OVER(PARTITION BY ItemValue ORDER BY ItemIndex, ItemValue)
    FROM
        @TempData
    ORDER BY
        ItemIndex;

    RETURN;
END;

GO

-- Get all non-empty and numeric items
SELECT * FROM dbo.fnArray2IntTable(N';444;bbb;333;;;333;444;555;', N';');
-- Get all non-empty and numeric items and filter non-unique
SELECT * FROM dbo.fnArray2IntTable(N';444;bbb;333;;;333;444;555;', N';') WHERE ItemRank=1;


Result of execution: