Quantcast
Channel: MSDN Blogs
Viewing all 12366 articles
Browse latest View live

Experience Windows 10, devices, Surface Book and teacher resources on the Stone 25th Anniversary Tour

$
0
0

In conjunction with Microsoft, Stone are taking to the roads of the UK to effectively showcase the latest innovative Windows tech for education and inspire you with the art of the possible. You’ll be able to get hands on with some new and innovative Windows devices from the likes of Toshiba and Acer and chat to experts from Stone, Microsoft and Tablet Academy who will advise you on how to use this tech effectively in the classroom to enhance teaching and learning.

...(read more)

Experience Windows 10, devices, Surface Book and teacher resources on the Stone 25th Anniversary Tour

$
0
0

In conjunction with Microsoft, Stone are taking to the roads of the UK to effectively showcase the latest innovative Windows tech for education and inspire you with the art of the possible. You’ll be able to get hands on with some new and innovative Windows devices from the likes of Toshiba and Acer and chat to experts from Stone, Microsoft and Tablet Academy who will advise you on how to use this tech effectively in the classroom to enhance teaching and learning.

...(read more)

Experience Windows 10, devices, Surface Book and teacher resources on the Stone 25th Anniversary Tour

$
0
0

In conjunction with Microsoft, Stone are taking to the roads of the UK to effectively showcase the latest innovative Windows tech for education and inspire you with the art of the possible. You’ll be able to get hands on with some new and innovative Windows devices from the likes of Toshiba and Acer and chat to experts from Stone, Microsoft and Tablet Academy who will advise you on how to use this tech effectively in the classroom to enhance teaching and learning.

...(read more)

Visual Studio Toolbox: Infrastructure as Code

$
0
0

In this episode, I am joined by Donovan Brown, who shows us infrastructure as code. This provides you the ability to take the infrastructure you want to host an app in and define it in code that can be checked into source code. These code files can server as Azure Resource Manager (ARM) templates, which can be used to spin up a pre-defined environment.

Parse DOM attribute object

$
0
0

When you are working on web development, you always need load the information from an attribute in a DOM. For example, you want to develop a web component to render input. User can use your component like following way.

<sample-input data-config="type: 'select', label: 'Gender', require: true, dropdown: [ 'Male', 'Female' ]"></sample-input>

In your implementation, you need load and deserialize the value of data-config attribute firstly. Perhaps you will write as following Type Script code since the value may be a JSON formatted without the outermost braces string which is like the value in style attribute.

export function attr(element: HTMLElement | string, name: string) {    var ele = !!element && typeof element === "string" ? document.getElementById(element) : element as HTMLElement;    if (!ele || !ele.tagName || !name) return undefined;    var attrStr = ele.getAttribute(name);    return eval("({" + attrStr + "})");
}

So that you can get following object as what you expect now.

{    type: 'select',    label: 'Gender',    require: true,    dropdown: ['Male', 'Female']
}

However, considering if you want to support function, array and JSON formatted object directly in the attribute, it does not work correctly. Because you add braces scope. Following is an example.

<sample-input data-config="function () { return null; }"></sample-input>

So you need check if it is a JSON formatted string without the outermost braces or not. So you should optimize the logic.

  1. Test if it is empty.
  2. Trim.
  3. Find if character "{" or ":" is in the string. If so, we should not add the outermost braces; otherwise, do as what you do before.

 So we have following code.

if (!attrStr) return null;
attrStr = attrStr.replace(/(^\s*)|(\s*$)/g, "");var indexA = attrStr.indexOf(":");var indexB = attrStr.indexOf("{");
attrStr = indexA > 0 && (indexB < 0 || indexA < indexB) ? eval("({" + attrStr + "})") : eval("(" + attrStr + ")");

 To support array, we need add following code.

if (indexA < 0 && indexB < 0 && attrStr.indexOf("="< 0 && attrStr.indexOf("'"< 0 &&    attrStr.indexOf("\""< 0 && attrStr.indexOf("("< 0 && attrStr.indexOf(")"< 0 && attrStr.indexOf(" "> 0) {    attrStr = attrStr.indexOf(";">= 0 ? attrStr.split(";") : attrStr as any;
}

For advanced functionality, you can add bind support like following to output a variable to the given attribute.

<sample-input data-config="{{dataConfig}}"></sample-input>

Following is a simple way. You can also optimize it to bind other information.

if (attrStr.indexOf("{{"=== 0 && attrStr.lastIndexOf("}}"=== attrStr.length - 2 && attrStr.length > 4) {    attrStr = eval("(" + attrStr.substring(2, attrStr.length - 2+ ")");
}

So you have finished the implementation of attribute parsing.

/**  * Parses the specific attribute object of an element.  * @param element  the element to get attribute.  * @param name  the attribute name.  */export function attr(element: HTMLElement | string, name: string) {    var ele = !!element && typeof element === "string" ? document.getElementById(element) : element as HTMLElement;    if (!ele || !ele.tagName || !name) return undefined;    var attrStr = ele.getAttribute(name);    if (!attrStr) return null;    attrStr = attrStr.replace(/(^\s*)|(\s*$)/g, "");    if (attrStr === ""return null;    if (attrStr.indexOf("{{"=== 0 && attrStr.lastIndexOf("}}"=== attrStr.length - 2 && attrStr.length > 4) {        return eval("(" + attrStr.substring(2, attrStr.length - 2+ ")");    }    var indexA = attrStr.indexOf(":");    var indexB = attrStr.indexOf("{");    if (indexA > 0 && (indexB < 0 || indexA < indexB)) return eval("({" + attrStr + "})");    if (indexA < 0 && indexB < 0 && attrStr.indexOf("="< 0 && attrStr.indexOf("'"< 0 &&        attrStr.indexOf("\""< 0 && attrStr.indexOf("("< 0 && attrStr.indexOf(")"< 0 && attrStr.indexOf(" "> 0) {        return attrStr.indexOf(";">= 0 ? attrStr.split(";") : attrStr as any;    }    return eval("(" + attrStr + ")");
}

Sometimes, people will not satisfy what they have owned currently. Although we have a way to parse attribute in a DOM, perhaps we want to find an easy way to do more. It will be cool if we can resolve an object which binds given attributes as its properties. So let's implement it now!

export function bindAttr(element: HTMLElement | string, names: string[]): any {    var ele = !!element && typeof element === "string" ? document.getElementById(element) : element as HTMLElement;    if (!ele || !ele.tagName || !names) return undefined;    var obj = {};    names.forEach(function (attrName, i, arr) {        var attr = attr(element, attrName);        obj[attrName] = attr;    });    return obj;
}

Now, we can load the attributes from a DOM to set as properties in an object to return. But if the attribute has been changed, we cannot get the notification. So we need add logic to register the event handler to listen.

ele.addEventListener("DOMAttrModified", (ev: any) => {    var attrName = ev.attrName || ev.propertyName;    if (!attrName || !names || !names.some((name, ni, narr) => {        return name === attrName;    })) return;    var attrObj = attr(element, attrName);    obj[attrName] = attrObj;
}, false);

And we can also add an argument to switch whether we need disable this feature. So we have optimized this function to bind.

/**  * Binds the objects parsed from specific attributes of an element to an object as its properties.  * @param element  the element to get attribute.  * @param names  the attribute name list.  * @param loadOnce  true if just load once without attribute listening; otherwise, false.  */export function bindAttr(element: HTMLElement | string, names: string[], loadOnce = false): any {    var ele = !!element && typeof element === "string" ? document.getElementById(element) : element as HTMLElement;    if (!ele || !ele.tagName || !names) return undefined;    var obj = {};    names.forEach(function (attrName, i, arr) {        var attr = attr(element, attrName);        obj[attrName] = attr;    });    if (!loadOnce) ele.addEventListener("DOMAttrModified", (ev: any) => {        var attrName = ev.attrName || ev.propertyName;        if (!attrName || !names || !names.some((name, ni, narr) => {            return name === attrName;        })) return;        var attrObj = attr(element, attrName);        obj[attrName] = attrObj;    }, false);    return obj;
}

You can continue to optimize this function to provide a way to notice outside when any attributes are changed and to remove the event listener by disposing.

Now, you can use these methods to load your data in DOM.

  • attr
    Parses the attribute object.
  • bindAttr
    Binds a set of attributes to an object as properties.

Enjoy!

Улучшения TFS 2015 Update 2 на примере работы с проблемами

$
0
0

TFS 2015 Update 2предлагает много различных обновлений, включая релиз менеджер, который теперь доступен через Web-интерфейс, а также работает с VMWare и System Center. Но есть также как, казалось бы, небольшие, но полезные функции. Например, функция подстановки отображаемого имени пользователя через символ «@». С использованием этого нововведения можно улучшить некоторые процессы внутри команды разработки, например, управление проблемами.

Зачастую этот процесс решается по довольно привычному пути — через телефон или корпоративную почту. Например, если возникает какой-либо вопрос, нужно что-либо уточнить, то инициатор в первую очередь пытается как-то решить проблему сразу личным общением, а если не получается, то начинает «писать письма». В больших компаниях таких писем очень много и существует много методик и советов как правильно работать с корпоративной почтой, но вряд ли все им следуют, что превращает почтовый ящик в солидный архив корреспонденции. Исходя из этого появляется небольшой список затруднений, связанных с электронной почтой:

  1. При большом количестве почты, включая обычно еще письма, в которых мы стоим просто в копии, получатель просто может упустить важное для него письмо и проблема долгое время остается незамеченной и нерешенной.
  2. Получатель может откладывать ответ для инициатора ввиду своей занятости, пока просто про него не забудет.
  3. Т.к. письмо в общем случае находится только в почтовых ящиках инициатора и получателя, то о процессе решения возникшей проблемы знает немного людей.
  4. Если в какой-то момент приходит точка Х, в которой нужно понять, что происходило, то это приводит к поиску в почтовом ящике, переборе потоков обсуждений и писем, а сделать это доступным для других участников можно только форвардом или распечатыванием потока обсуждения.
  5. Т.к. почта остается в личном ящике, то полученный опыт при решении проблем не может быть доступен для всех участников команды. А это может привести к повторному прохождению пути при решении схожих или этих же проблем.
  6. Невозможно понять сколько проблем у нас возникает, сколько мы решили, сколько еще нужно решить и сколько мы потратили на это времени.

Использование TFS может помочь упростить этот процесс:

  • Для управления проблемами в различных шаблонах существуют необходимые рабочие элементы, например, CMMI имеет Проблемы, Agile — Проблемы, Scrum – Препятствия. Инициатор создает соответствующий рабочий элемент в командном проекте, назначает на исполнителя, который может решить проблему, и она доступна всем участникам разработки, включая руководителя проекта. Использование рабочего элемента позволяет определить правила обработки и эскалации при решении проблем.
  • Через символ «@» к решению проблемы можно привлечь необходимое количество людей, которые могут что-то подсказать или направить по нужному пути. Данную возможность можно использовать в комментариях для рабочего элемента, при этом участникам будет отправлено системой оповещение.

Рисунок 1. добавление участников к обсуждению

Рисунок 2. Пример нотификации

  • Запросы по рабочим элементам позволяют видеть, что у нас с проблемами в проекте, что с моими проблемами, а также, что происходит с проблемами, в которых я участвовал. Это решается с использованием поиска соответствующего отображаемого имени поле Кому назначено, Кем создано и в истории рабочих элементов.

Рисунок 3. Пример запроса по рабочим элементам

  • Использование Report Server позволит собрать отчетную информацию по нашим проблемам, в том числе, если вы используете TimeSheet, что обсуждалось ранее, то вы можете учитывать время, которое было потрачено на их решение.
  • Все проблемы остаются в TFS, поэтому всегда можно организовать поиск их решения через запросы по рабочим элементам и через стандартный механизм быстрого поиска TFS.

How to determine the DWU setting for a SQL Data Warehouse

$
0
0

Azure SQL Data Warehouse service allows you to dynamically size the amount of compute resources within seconds. The setting for the amount of DWU (Data Warehouse Units = compute power) that is assigned can be viewed by opening the Azure Portal and viewing the database blade:

The SQL team has now introduced a new DMV (sys.database_service_objectives) that allows you to programmatically access the DWU setting. You will need to connect to the master database of your logical server and you can run this query:

SELECT
db.name [Database],
ds.edition [Edition],
ds.service_objective [Service Objective]
FROM
sys.database_service_objectives ds
JOIN sys.databases db ON ds.database_id = db.database_id
 
This will return all of the databases and their Service Objective (the column that contains the DWU setting) on the logical server.
In this sample, you can see a logical server that contains 3 Data Warehouse and 1 Azure SQL Database databases. You can also filter for just SQL Data Warehouses:
 
SELECT
db.name [Database],
ds.edition [Edition],
ds.service_objective [Service Objective]
FROM
sys.database_service_objectives ds
JOIN sys.databases db ON ds.database_id = db.database_id
WHERE
ds.edition = 'DataWarehouse'

 

To learn more about Azure SQL Data Warehouse, visit the main product page

Master Data Services - SQL2016 RC1(March) is Released

$
0
0

What is New:

Added negate operators support for Business Rules.

Sample Model Deployment Packages Updated.

Download Links:

SQL Server 2016 : https://www.microsoft.com/en-us/evalcenter/evaluate-sql-server-2016

MDS Excel add in : http://go.microsoft.com/fwlink/?LinkID=398159

 


Master Data Services - SQL2016 RC0(February) is Released

Delay task

$
0
0

Consider there is a scenario like that a user can search something by typing words in a textbox. The app will send request to the server for query result. But you may want to delay the request sending because the user is still typing. You will send the latest information after the user stop to type after a short while and ignore the ones during typing.

To abstract this, we can design a delay task with following goals to implement it.

  • Generates a task to control when to run a given handler.
  • Process the handler after a specific time span when the task starts.
  • The task can be run by several times.
  • Do not process the handler if the task is run again before it processes.

I will introduce this implementation in both of Type Script and C#.

Type Script

Let's define the options interface for the delay task.

/**  * Options to set the delay task.  */export interface DelayOptionsContract {    /**      * The business handler to process.      * @param modelArg  An optional argument.      */    process(modelArg?: any): void;    /**      * The timespan in millisecond for waiting.      */    delay?: number;    /**      * The object to be used as the current object      * for handler processing.      */    thisArg?: any;
}

Then we need add a function that generates the task by the way described by the options.

export function delay(options: DelayOptionsContract)    : (modelArg?: any) => void {    // ToDo: Implement it.    return null;}

Sounds we need implement it by this way.

return (modelArg?: any) => {    setTimeout(() => {        options.process(modelArg);    }, options.delay);};

However, it will process twice or more when the user run the task several times between the time span less than the one in options. So we need update it to add the status and checking to ignore this. We can just use an increasable number as the status value for checking. We need also add a new handler for processing the handler registered after status checking.

var token = 0;var handler = (modelArg: any, testToken: number) => {    if (testToken !== token)return;    options.process.call(options.thisArg, modelArg);};

The function should return following result to call the new handler.

return (modelArg?: any) => {    token++;    setTimeout(handler, options.delay,modelArg,token);};

For a better solution, we can clear the timeout callback when the task is run again.

var timeout: number;return (modelArg?: any) => {    token++;    clearTimeout(timeout);    if (!!timeout)        clearTimeout(timeout);    timeout = setTimeout(        handler,        options.delay,        modelArg,        token);};

Clearing the timeout token should be also added in the new handler. After add the empty arguments checking, it will look like this.

/**  * Generates a delay task.  * @param options  The options to load.  */export function delay(options: DelayOptionsContract)    : (modelArg?: any) => void {    if (!options || !options.process)        return null;    var token = 0;    var timeout: number;    var handler = (modelArg: any, testToken: number) => {        timeout = null;        if (testToken !== token)            return;        options.process.call(options.thisArg, modelArg);    };    return (modelArg?: any) => {        token++;        clearTimeout(timeout);        if (!!timeout)            clearTimeout(timeout);        timeout = setTimeout(            handler,            options.delay != null ? options.delay : 0,            modelArg, token);    };}

Now we can have a test.

var task = delay({    delay: 300,    process: function (model) {        console.debug(model);    }});document.body.addEventListener(    "click",    function (ev) {        task(new Date().toLocaleTimeString());    },    false);

You will see it works well. And of course, you can continue to add promise support.

C#

Firstly, we need add some references for using.

using System;using System.Threading;using System.Threading.Tasks;

Then we can define a class with a property to set the timeout span and an event for registering the one which will be occurred after the task processing. An async method is provided to call to process the task after the specific time span.

public class DelayTask
{    public TimeSpan Span { getset; }    public event EventHandler Processed;    public async Task<bool> Process()    {        throw new NotImplementedException();    }
}

In process method, we need delay to execute and raise the event. To ignore the processing of the ones raised before the previous one finished, we need add a token to check.

private Guid _token = Guid.Empty;

The token should be generated, checked and cleared during processing. The result is a status indicating whether it executes.

public async Task<bool> Process()
{    var token = Guid.NewGuid();    _token = token;    await Task.Delay(Span);    if (token != _token) return false;    _token = Guid.Empty;    Processed(thisnew EventArgs());    return true;
}

And add a cancellable process method. Now we get the following task.

/// <summary>/// The delay task./// </summary>public class DelayTask
{    private Guid _token = Guid.Empty;    /// <summary>    /// Gets or sets the delay time span.    /// </summary>    public TimeSpan Span { getset; }    /// <summary>    /// Adds or removes the event handler occurred    /// after processed.    /// </summary>    public event EventHandler Processed;    /// <summary>    /// Processes the delay task.    /// </summary>    /// <returns>    /// A task with a value indicating whether it executes.    /// </returns>    public async Task<bool> Process()    {        return await Process(CancellationToken.None);    }    /// <summary>    /// Processes the delay task.    /// </summary>    /// <param name="cancellationToken">    /// The cancellation token that will be checked prior    /// to completing the returned task.    /// </param>    /// <returns>    /// A task with a value indicating whether it executes.    /// </returns>    public async Task<bool> Process(        CancellationToken cancellationToken)    {        var token = Guid.NewGuid();        _token = token;        await Task.Delay(Span, cancellationToken);        if (token != _token) return false;        _token = Guid.Empty;        if (cancellationToken.IsCancellationRequested)            return false;        Processed(thisnew EventArgs());        return true;    }
}

To use it, you just need create an instance of this class with delay time span and call its process member method where you need execute the task. You can also register the event handler for processing.

Multiple hit task

$
0
0
We always need process a business logic after a multiple hit such as double or more click event. And sometimes there is no such event handler to register so that we need find a way to do so. One of solutions is to design a task including following goals.
  • Can register a handler to process after a multiple hit.
  • The task can be run anywhere including in the event such as click.
  • It executes the handler only when the task is run by the given times.
  • The hit count will be reset if it is timeout after previous running.

I will introduce how to implement in both Type Script and C#.

Type Script

Firstly, we can define an options interface for initializing the task. We expect the user can set a process handler, and can customize how many hits to start processing and end, and config the timeout between two hits.

/**  * Options of multiple hit task.  */export interface MultipleHitOptionsContract {    /**      * The business handler to process.      * @param index  The index of current hit.      * @param modelArg  An optional argument.      */    process(index: number, modelArg?: any): void;    /**      * Start for hitting.      */    start?: number;    /**      * Hitting count.      */    count?: number;    /**      * The timespan in millisecond for hitting.      */    timeout?: number;    /**      * The object to be used as the current object      * for handler processing.      */    thisArg?: any;
}

Then we can write a function to generate a task. It requires the option and returns a value indicating whether the handler is processed.

export function multiplHit(    options: MultipleHitOptionsContract)    : (modelArg?: any) => boolean {    if (!options || !options.process        || options.count === 0)        return null;    // ToDo: Implement it.    return null;
}

If the maximum hit count is not set, and start index is set to 0 or null, we just process the handler direct and return true.

if (!options.start && options.count == null) {    return (modelArg?: any) => {        options.process.call(            options.thisArg,            0,            modelArg);        return true;    };
}

Otherwise, we need a counter and a date to record how many and when the current hit is processed.

var count = 0;var time: Date = null;

Then we need create a function to return.

return (modelArg?: any) => {    options.process.call(        options.thisArg,        count - 1,        modelArg);    return true;
};

Before executing the handler, we need check the previous time and record current one.

var timespan = time != null    ? new Date().getTime() - time.getTime()    : null;
time = new Date();if (timespan == null    || timespan > options.timeout) {    count = 1;    return false;
}

And check the count to determine if need execute.

count++;var start = !!options.start    ? options.start    : 0;if (count < start    || (options.count != null        && options.count <= count - start))    return false;

So we get following task generator now.

/**  * Generates a multiple hit task.  * @param options  The options to load.  */export function multipleHit(    options: MultipleHitOptionsContract)    : (modelArg?: any) => boolean {    if (!options        || !options.process        || options.count === 0return null;    if (!options.start && options.count == null) {        return (modelArg?: any) => {            options.process.call(                options.thisArg,                0,                modelArg);            return true;        };    }    var count = 0;    var time: Date = null;    return (modelArg?: any) => {        var timespan = time != null            ? new Date().getTime() - time.getTime()            : null;        time = new Date();        if (timespan == null            || timespan > options.timeout) {            count = 1;            return false;        }        count++;        var start = !!options.start            ? options.start            : 0;        if (count < start            || (options.count != null                && options.count <= count - start))            return false;        options.process.call(            options.thisArg,            count - 1,            modelArg);        return true;    };
}

Now we can have a test.

export function multipleHitTest() {    var task = multipleHit({        timeout: 300,        start: 3,        count: 100,        process: function (index, model) {            console.debug(index.toString()                + " at " + model);        }    });    document.body.addEventListener(        "click",        function (ev) {            task(new Date().toLocaleDateString());        },        false);
}

It will log debug info to console only when you click 3 times to 100 times quickly in the page.

C#

We need implement a class to provide a member method to process anywhere. The method should return a value indicating whether the context condition is matched. User can set start index, end index and timeout.

public class MultipleHitTask
{    public int Start    { getset; }    public int End    { getset; }    public TimeSpan Timeout    { getprivate set; }    public DateTime LatestProcess    { getprivate set; }    public int HitCount    { getprivate set; }    public event EventHandler Processed;    public bool Process()    {        throw new NotImplementedException();    }
}

The event is used to register to occur so that user can add the handler. The current index should be provided.

/// <summary>/// The event arguments with counting./// </summary>public class IndexEventArgsEventArgs
{    /// <summary>    /// Gets the index.    /// </summary>    public int Index { getprivate set; }    /// <summary>    /// Initializes a new instance    /// of the IndexEventArgs class.    /// </summary>    /// <param name="index">The index.</param>    public IndexEventArgs(int index)    {        Index = index;    }
}

So the event in the class should also update like this way.

public event EventHandler<IndexEventArgs> Processed;

In the process method, we should execute the handler.

var args = new IndexEventArgs(HitCount - 1);
Processed(this, args);return true;

And we need add the checking logic.

var now = DateTime.Now;if (LatestProcess == null    || now - LatestProcess > Timeout)
{    HitCount = 0;
}
HitCount++;if (HitCount <= Start || HitCount > End)    return false;

So following is the class.

/// <summary>/// Multiple hit task./// </summary>public class MultipleHitTask
{    /// <summary>    /// Gets or sets the start index of hit to process.    /// </summary>    public int Start { getset; }    /// <summary>    /// Gets or sets the end index of hit to process.    /// </summary>    public int End { getset; }    /// <summary>    /// Gets the timeout.    /// </summary>    public TimeSpan Timeout { getprivate set; }    /// <summary>    /// Gets the time of latest processing.    /// </summary>    public DateTime LatestProcess { getprivate set; }    /// <summary>    /// Gets the hit count.    /// </summary>    public int HitCount { getprivate set; }    /// <summary>    /// Adds or removes the event handler occured    /// after processing    /// </summary>    public event EventHandler<IndexEventArgs> Processed;    /// <summary>    /// Processes the task.    /// </summary>    /// <returns>true if match the condition to execute;    /// otherwise, false.</returns>    public bool Process()    {        var now = DateTime.Now;        if (LatestProcess == null            || now - LatestProcess > Timeout)        {            HitCount = 0;        }        HitCount++;        if (HitCount <= Start || HitCount > End)            return false;        var args = new IndexEventArgs(HitCount - 1);        Processed(this, args);        return true;    }
}

You can create an instance of this class and register the event handler. Then execute process member method anywhere.

Decoding Idea Submission Round for Imagine Cup

$
0
0

Decoding Idea Submission Round of Imagine Cup

We have had a lot of buzz around Imagine Cup these days as idea submission deadlines are approaching. Imagine Cup is a global student technology program and competition that provides opportunities for students across all disciplines to team up and use their creativity, passion and knowledge of technology to create applications, games and integrate solutions that can change the way we live, work and play.

Imagine Cup will provide you an opportunity to bring your bold ideas to life. I can’t think of a big opportunity to turn your dreams into reality and taking the first step in turning it into a business during student life.

The good thing about Imagine Cup is it gives chance to almost all students to try their luck and to participate with any skill set. Imagine Cup has competitions and contests are divided into 3 categories, according to their technical aptitude:

  1. Beginner – No or little coding required
  2. Medium – Some experience in Coding
  3. Advanced – Experienced Student Developers

This time, we have 3 global competitions and 2 online contests in Imagine Cup.

During my college days, I always participated in multiple technical contests. There are typically 3 important phases for any competition:

  1. Ideation and Conceptualization
  2. Implementation
  3. Packaging and Presentation

Ideation and Conceptualization: With a hypothesis that you have already formed your dream team for the competition, the next crucial phase is all about ideation and preparing concept note. There are multiple ways to go about Ideation process:

  1. Read rules and regulations of the event and properly tabulate all the important things
  2. If it’s a theme based competition, discuss with your team and go ahead with one theme in which you have some knowledge or feel comfortable talking about it.
  3. Create list of all the ideas which comes to floor during brainstorming with your team.

Pro Tip: Search online and check various submissions and innovative ideas; it’s highly unlikely that something may click to you which is a combination of some really cool stuff

  1. Choose top 3 best ideas and now start preparing concept note. Once you are done with it, Prepare a one slider for technical implementation.

Pro Tip: Take advice of your seniors or mentors in validation of your technical implementation idea. Sometimes some ideas can be a bit superficial and imposable to implement.

  1. Finalize your idea and turn your one-page concept note into a proper project document which has all the typical project document contents
  2. Create your first 10 Slider presentation for your idea along with a design document containing architecture and step wise implementation steps/

Implementation:

  1. If you have followed all the steps of Ideation and Planning, It will be a very easy and straight forward process in terms of giving shape to your idea. Take help of seniors and experts as and when you get stuck. Don't try to find solution to each and every problem. As I am a firm believer of component based Software Engineering, I suggest trying out the already developed libraries and solutions. 
Pro Tip: Try to get final output as soon as possible, Don't bother about UI and Design way too much over here. You can always showcase the planned UI and UX in concept note document or in the presentation video. 
Packaging and Presentation:
1. Its very critical that before the final submission, your presentation does justice to your idea and your grand thoughts. Always make sure that you send the right message to judges. Use images as much as you canand try to show live demo during recording video. 
 
So - Until next time, That's all from my end. Looking forward for your tweets with comments and suggestions at http://twitter.com/NowayheCodes :)

SET STATISTICS IO

$
0
0

Há 20 anos quando comecei a estudar banco de dados, imaginava que o SQL era uma caixa-preta. Bastava inserir os dados e não precisaria me preocupar mais. Eu era um desenvolvedor sem conhecimento de banco de dados.

Para relembrar esse cenário, vou criar um banco de dados chamado LOJADB usando um pendrive (meu storage de 8GB).

image

Usei um script simples com o único cuidado de deixar o espaço pré-alocado e sem Auto-Growth para evitar surpresas nos testes.

image

Nesse banco de dados, havia uma tabela de cadastro de clientes. Simplificando, seria algo assim:

image

Voltando ao passado, comecei a inserir os dados no banco de dados. Era uma rotina aparentemente simples, mas demorava demais. A rotina levou cerca de 85 segundos para completar e inserir 10.000 registros – dividindo, dá 117 linhas por segundo. Na época isso chamou minha atenção, pois imaginava que tudo no banco de dados fosse rápido!

image

Comecei a executar alguns comandos e eles rodavam imediatamente!

image

Em seguida fazia consulta de cliente e o resultado era instantâneo!

image

Essa foi minha primeira experiência com banco de dados: aparentemente as inserções eram lentas, mas as consultas eram rápidas.

 

SET STATISTICS

Se você já foi desenvolvedor e vivenciou essa situação, então preste atenção ao comando SET STATISTICS. Esse foi o comando que abriu os meus olhos para entender como que um banco de dados funciona.

Primeiro vamos rodar o comando SET STATISTICS TIME.

SET STATISTICS TIME
https://msdn.microsoft.com/en-us/library/ms190287.aspx

image

O resultado do SET STATISTICS TIME mostra que a execução durou apenas 1ms, que é um resultado excelente!

Em seguida, rodei o comando SET STATISTICS IO.

SET STATISTICS IO
https://msdn.microsoft.com/en-us/library/ms184361.aspx

image

Isso me surpreendeu, pois não imaginava ver 1257 logical reads (parece um valor alto?). Fiquei curioso para entender o significado de cada um dos valores.

  • Scan count: Número de scan em tabelas
  • Logical reads: Quantidade de páginas lidas (memória ou disco)
  • Physical reads: Quantidade de páginas lidas do disco
  • Read-ahead reads: Quantidade de páginas lidas com prefetch
  • Lob logical reads, lob physical reads, lob read-ahead reads: Contador de acesso aos large object (ex: TEXT) – desconsidere, por enquanto.

As consultas no banco de dados eram feitas todas em memória sem a necessidade de ir ao disco. Por isso, repeti os testes com SET STATISTICS TIME e IO, mas antes rodei o comando DBCC DROPCLEANBUFFERS. Isso eliminaria o cache em memória e forçaria o acesso ao disco.

image

Nesse cenário, a consulta demorou 369ms. Executando o comando novamente sem limpar o cache:

image

O tempo voltava para 1ms como esperado.

Conclusão

Surpresa? Espero que não. Trabalhar com dados em cache é muito mais rápido.

Termino esse artigo relembrando que o disco é o principal recurso do SQL Server. Eu poderia perder muito tempo fazendo otimizações com base no SET STATISTICS TIME ao invés de usar o STATISTICS IO. Monitore o disco. Priorize o disco. Minha dica é que, se você não conhece o SET STATISTICS IO, então invista parte do tempo para entender esse comando. Ele é uma das melhores ferramentas de aprendizado.

Nota: Você notou que um dos resultados do SET STATISTICS IO retornou 1257 logical reads e 823 read-aheads? Não deveriam ser iguais? No próximo post vamos explorar melhor o comando DBCC DROPCLEANBUFFERS e explicar esse comportamento.

Warehouse Location directives - Fixed location usage

$
0
0

Setting up location directives for your warehouse in AX2012 R3 and AX7 requires a lot of attention to detail. The directives are extremely powerful, but also open ended, which can lead to both performance and logistical problems. This article on MSDN gives a good overview, but doesn't provide any deep dives.

This post is intended to explain the "Fixed location usage" option on the location directive lines.

The setting pretty much answers the question "Which locations should be considered for put-away of the item?"

Work type

Fixed location usage

Behavior

Pick

<any>

<Setting is ignored>

Put

Fixed and non-fixed locations

<Setting is ignored>

 

In other words: All locations are considered for the product. If the product has fixed location that information is not leveraged, this means that non-fixed locations are considered as well as locations that are fixed to other items.

Put

Only fixed locations for the product

An exists join on WHSInventFixedLocation on itemid is added to the WMSLocation datasource in the query

 

In other words: Only fixed locations for the product are considered.

Put

Only fixed locations for the product variant

As above, except the exists join is on both ItemId and InventDim

 

In other words: Only fixed locations for the product variant are considered

 

If you are using fixed locations for any product or product variant you can gain substantial performance benefits by having an action line to look at the fixed location before looking across locations – similar to the picture above.

Example

Consider a simple warehouse with 1000 items and 1000 locations. A subset of the items have a fixed location. Each location has infinite capacity – but doesn't allow mixed items.

Location directive setup

Item received

Number of locations considered (*)

1. Only fixed locations for the product
2. Fixed and non-fixed locations

Fixed location
Non-fixed location

1
1000

1. Fixed and non-fixed locations

Fixed location
Non-fixed location

1000
1000

*: The location directives will stop searching when the first qualifying location is found – so the above number only illustrates the worst case.

In other words: Finding the put-away location for a fixed location item is now an order of magnitude faster.

Investigating issues with Visual Studio Team Services - 3/22 - Investigating

$
0
0
Initial Update: Tuesday, 22 March 2016 17:16 UTC

We are actively investigating issues with User Hub where users might experience errors intermittently while accessing user hub from the Visual Studio Team Services accounts.

We are working to resolve this issue and apologize for any inconvenience.

Sincerely,
Manjunath
 

Add Structure to Your Diagrams in Microsoft Visio 2016

$
0
0

This chapter from Microsoft Visio 2016 Step By Step guides you through procedures related to organizing shapes by using containers or lists, finding containers and lists in Visio, and annotating shapes by using callouts.

In this chapter

  • Understand containers, lists, and callouts
  • Compare groups and containers
  • Organize shapes by using containers
  • Organize shapes by using lists
  • Find containers and lists in Visio
  • Annotate shapes by using callouts

Practice files

For this chapter, use the practice files from the Visio2016SBS\Ch13 folder. For practice file download instructions, see the introduction.

In many types of Visio diagrams, it’s useful to create visual or logical relationships among a set of shapes. The traditional technique for doing this in Visio has been to use background shapes and groups. However, Visio 2016 offers three special shape types—containers, lists, and callouts—that can be even more effective when you want to establish relationships and add structure to your diagrams.

Structured diagram shapes are so useful that Visio itself relies on them for a growing number of templates and special uses. For example, you will find lists and containers in swimlane diagrams, wireframes, and data graphic legends; and you will encounter callouts in the Business Process Model and Notation (BPMN) template (Visio Professional only).

Read the complete chapter here.

Slide on web

$
0
0

It can improve user experience to support sliding by touching and mouse for some components, e.g. slider, content flipping, jump list menu, etc. In web development, we can use some event to implement it. But how can we abstract it for generic usages? Let's make some goals to support.

  • Target to an element.
  • Slide left/right/top/bottom event.
  • Minimum horizontal/vertical displacement.
  • Moving event.

Then we will translate these into Type Script.

Contracts

We need following options contract to customized a slide behavior for a specific element.

/**  * Slide options.  */export interface SlideOptionsContruct {     /**      * The mininum horizontal value      * to active related gesture handlers.      */    minX?: number;     /**      * The mininum vertical value      * to active related gesture handlers.      */    minY?: number;     /**      * The handler rasied on turning up.      * @param ele  The target element.      * @param x  The distance moved in horizontal.      */    turnUp?(ele: HTMLElement, x: number): void;     /**      * The handler rasied on turning right.      * @param ele  The target element.      * @param x  The distance moved in horizontal.      */    turnRight?(ele: HTMLElement, x: number): void;     /**      * The handler rasied on turning down.      * @param ele  The target element.      * @param y  The distance moved in vertical.      */    turnDown?(ele: HTMLElement, y: number): void;     /**      * The handler rasied on turning left.      * @param ele  The target element.      * @param y  The distance moved in vertical.      */    turnLeft?(ele: HTMLElement, y: number): void;     /**      * The handler rasied before moving.      * @param ele  The target element.      */    moveStart?(ele: HTMLElement): void;     /**      * The handler rasied after moving.      * @param ele  The target element.      * @param x  The distance moved in horizontal.      * @param y  The distance moved in vertical.      */    moveEnd?(        ele: HTMLElement,        x: number,        y: number): void;     /**      * The handler rasied on moving.      * @param ele  The target element.      * @param x  The distance moved in horizontal.      * @param y  The distance moved in vertical.      */    moving?(        ele: HTMLElement,        x: number,        y: number): void;
}

And the signature of the function to bind the slide gesture should be like this. It returns a disposable object so that the user can cancel remove the behavior.

export function addSlide(    element: HTMLElement | string,    options: SlideOptionsContruct)    : { dispose(): void } {    if (!options || !element) return {        dispose: () => { }    };    var ele = !!element        && typeof element === "string"        ? document.getElementById(element)        : element as HTMLElement;    if (!ele) return {        dispose: () => { }    };    // ToDo: Implement it.    return null;
}

The function has 2 arguments, one is the target element, the second is the options. We need validate the arguments firstly and then add implementation. It needs support both touch and mouse.

Touch

Touch includes finger touching, pen drawing and other screen touching input. To make words simple, I just use finger touching to refer all kinds of touching input here. For adding a gesture supports, we need know how browser raise event to the web pages.

  1. When you use your finger touch the screen, a touch start event is raised.
  2. During you slide in the screen by your finger, the touch move event is raised continuously.
  3. When your finger leaves screen, a touch end event is raised.

So, we can use these event to implement. For touch start, we need record where the finger is at beginning.

var start: { x: number, y: number } = null;var touchStart = (ev: TouchEvent) => {    start = {        x: ev.targetTouches[0].pageX,        y: ev.targetTouches[0].pageY    };    if (!!options.moveStart)        options.moveStart(ele);
};
ele.addEventListener(    "touchstart",    touchStart,    false);

Then we can check this value later to compute the distance of sliding. Now we can implement touch move event by getting the current touching position minus the one beginning. And call the handler registered.

var touchMove = !!options.moving    ? (ev: TouchEvent) => {        var point = (ev.touches            ? ev.touches[0]            : ev) as Touch;        if (!point) return;        var coor = {            x: point.pageX - start.x,            y: point.pageY - start.y        };        options.moving(ele, coor.x, coor.y);    }    : null;if (!!touchMove)    ele.addEventListener(        "touchmove",        touchMove,        false);

For end, we need compute if the end user has moved the element by checking the distance of current one and the minimum values. We need also judge if it is turn left or right, and turn up or turn down.

var moved = (x: number, y: number) => {    var isX = !|| (Math.abs(x) / Math.abs(y)        > (minX + 0.01/ (minY + 0.01));    if (isX) {        if (x > minX && !!options.turnLeft)            options.turnLeft(ele, x);        else if (x < -minX && !!options.turnRight)            options.turnRight(ele, -x);    } else {        if (y > minY && !!options.turnUp)            options.turnUp(ele, y);        else if (y < -minY && !!options.turnDown)            options.turnDown(ele, -y);    }    if (!!options.moveEnd)        options.moveEnd(ele, x, y);
};

Now, we can call this function in touch end event.

var touchEnd = (ev: TouchEvent) => {    if (start == nullreturn;    var x = ev.changedTouches[0].pageX - start.x;    var y = ev.changedTouches[0].pageY - start.y;    start = null;    moved(x, y);
};
ele.addEventListener(    "touchend",    touchEnd,    false);

Touch events listening is done.

Mouse

Currently, it does not work for mouse if you just implement as this. So let's continue to add mouse events supports.

Before of this, we need have a way to get the position of the mouse in the document. The way to get the mouse position in the page is simple, it is by following way.

  1. Load them from event object. If not support, continue to next step; otherwise, return.
  2. Get where the page scrolls and where the mouse is in current screen. Then add them. Return.

Additional, if you are implementing a common function, you need also support touch, although it may not for this subject because we have the way to handle touch scenario. The way to get touch position is to load data from event data, too.

Following is the code.

/**  * Gets the position of the mouse in document.  */export function getMousePosition()    : { x: number, y: number } {    // Resolve mouse position.    var x = (event as any).pageX        || ((event as any).clientX            + (document.documentElement.scrollLeft                || document.body.scrollLeft));    var y = (event as any).pageY        || ((event as any).clientY            + (document.documentElement.scrollTop                || document.body.scrollTop));    // Resolve touch position.    var evTouches: TouchList        = (event as any).touches;    if (!!evTouches        && !!evTouches.length        && evTouches.length > 0        && !!evTouches[0]) {        if (isNaN(x) || x == null)            x = evTouches[0].pageX;        if (isNaN(y) || y == null)            y = evTouches[0].pageX;    } else {        evTouches            = (event as any).changedTouches;        if (!!evTouches            && !!evTouches.length            && evTouches.length > 0            && !!evTouches[0]) {            if (isNaN(x) || x == null)                x = evTouches[0].pageX;            if (isNaN(y) || y == null)                y = evTouches[0].pageX;        }    }    // Return result as a coordinate.    return { x: x, y: y };
}

So it can get mouse position or touch position. Now, let's turn back to the main function.

If an end user uses the mouse to slide, a series events will be raised.

  1. A mouse down event.
  2. Continuous mouse move events.
  3. A mouse up event.

The user need keep pressing the mouse button to do the action. So everything about moving will be in mouse down event.

var mouseDown = (ev: MouseEvent) => {    var mStartP = getMousePosition();    // ToDo: Implement it.
};
ele.addEventListener(    "mousedown",    mouseDown,    false);

After get the mouse position in mouse down event handler, we need register mouse move event handler to call moving handler registered in options.

var mouseMove = (ev: MouseEvent) => {    var mCurP = getMousePosition();    var x = mCurP.x - mStartP.x;    var y = mCurP.y - mStartP.y;    options.moving(ele, x, y);
};
document.body.addEventListener(    "mousemove",    mouseMove,    false);

And also mouse up event handler. The mouse up handler needs call the end moving function. But before this, it needs remove the both of mouse move event handler and mouse up event handler itself; otherwise, they will not release after end moving. To implement the release logic, we can use a list to record which handlers should be processed. Then register the mouse up handler to run the list one by one.

var mouseUpHandlers = [];var mouseUp = (ev: MouseEvent) => {    mouseUpHandlers.forEach((h, hi, ha) => {        h(ev);    });
};
mouseUpHandlers.push(    () => {        document.body.removeEventListener(            "mousemove",            mouseMove,            false);    },    () => {        document.body.removeEventListener(            "mouseup",            mouseUp,            false);    },    (ev: MouseEvent) => {        var mCurP = getMousePosition();        var x = mCurP.x - mStartP.x;        var y = mCurP.y - mStartP.y;        moved(x, y);    }
);
document.body.addEventListener(    "mouseup",    mouseUp,    false);

So it can handle mouse events now.

Complete rest

After these, we need return a disposable object to support removing these event handlers.

return {    dispose: () => {        // Remove touch events.        ele.removeEventListener(            "touchstart",            touchStart,            false);        if (!!touchMove)            ele.removeEventListener(                "touchmove",                touchMove,                false);        ele.removeEventListener(            "touchend",            touchEnd,            false);        // Remove mouse event.        ele.removeEventListener(            "mousedown",            mouseDown,            false);    }
};

Now, we have completed this function. Following is the code.

/**  * Adds gesture handlers.  * @param element  the target element.  * @param options  the options.  */export function addSlide(    element: HTMLElement | string,    options: SlideOptionsContruct)    : { dispose(): void } {    if (!options || !element) return {        dispose: () => { }    };    // Get the element.    var ele = !!element        && typeof element === "string"        ? document.getElementById(element)        : element as HTMLElement;    if (!ele) return {        dispose: () => { }    };    // Get the minimum moving distances.    var minX: number = options.minX;    var minY: number = options.minY;    if (minX == null || minX < 0) minX = 1;    minX = Math.abs(minX);    if (minY == null || minY < 0) minY = 1;    minY = Math.abs(minY);    // The handler occured after moving.    var moved = (x: number, y: number) => {        var isX = !|| (Math.abs(x) / Math.abs(y)            > (minX + 0.01/ (minY + 0.01));        if (isX) {            if (x > minX && !!options.turnLeft)                options.turnLeft(ele, x);            else if (x < -minX && !!options.turnRight)                options.turnRight(ele, -x);        } else {            if (y > minY && !!options.turnUp)                options.turnUp(ele, y);            else if (y < -minY && !!options.turnDown)                options.turnDown(ele, -y);        }        if (!!options.moveEnd)            options.moveEnd(ele, x, y);    };    // Touch starting event handler.    var start: { x: number, y: number } = null;    var touchStart = (ev: TouchEvent) => {        start = {            x: ev.targetTouches[0].pageX,            y: ev.targetTouches[0].pageY        };        if (!!options.moveStart)            options.moveStart(ele);    };    ele.addEventListener(        "touchstart",        touchStart,        false);    // Touch moving event handler.    var touchMove = !!options.moving        ? (ev: TouchEvent) => {            var point = (ev.touches                ? ev.touches[0]                : ev) as Touch;            if (!point) return;            var coor = {                x: point.pageX - start.x,                y: point.pageY - start.y            };            options.moving(ele, coor.x, coor.y);        }        : null;    if (!!touchMove)        ele.addEventListener(            "touchmove",            touchMove,            false);    // Touch ending event handler.    var touchEnd = (ev: TouchEvent) => {        if (start == nullreturn;        var x = ev.changedTouches[0].pageX - start.x;        var y = ev.changedTouches[0].pageY - start.y;        start = null;        moved(x, y);    };    ele.addEventListener(        "touchend",        touchEnd,        false);    // Mouse event handler.    var mouseDown = (ev: MouseEvent) => {        // Record current mouse position        // when mouse down.        var mStartP = getMousePosition();        // Mouse moving event handler.        var mouseMove = (ev: MouseEvent) => {            var mCurP = getMousePosition();            var x = mCurP.x - mStartP.x;            var y = mCurP.y - mStartP.y;            options.moving(ele, x, y);        };        document.body.addEventListener(            "mousemove",            mouseMove,            false);        // Mouse up event handler.        // Need remove all mouse event handlers.        var mouseUpHandlers = [];        var mouseUp = (ev: MouseEvent) => {            mouseUpHandlers.forEach((h, hi, ha) => {                h(ev);            });        };        mouseUpHandlers.push(            () => {                document.body.removeEventListener(                    "mousemove",                    mouseMove,                    false);            },            () => {                document.body.removeEventListener(                    "mouseup",                    mouseUp,                    false);            },            (ev: MouseEvent) => {                var mCurP = getMousePosition();                var x = mCurP.x - mStartP.x;                var y = mCurP.y - mStartP.y;                moved(x, y);            }        );        document.body.addEventListener(            "mouseup",            mouseUp,            false);    };    ele.addEventListener(        "mousedown",        mouseDown,        false);    // Return a disposable object    // for removing all event handlers.    return {        dispose: () => {            // Remove touch events.            ele.removeEventListener(                "touchstart",                touchStart,                false);            if (!!touchMove)                ele.removeEventListener(                    "touchmove",                    touchMove,                    false);            ele.removeEventListener(                "touchend",                touchEnd,                false);            // Remove mouse event.            ele.removeEventListener(                "mousedown",                mouseDown,                false);        }    };

Now you can have a test. Suppose we have following elements.

<div id="demo_gesture">    <div id="demo_gesture_fore">        &nbsp;    </div></div>

The style is following.

#demo_gesture {    max-width800px;    height20px;    background-color#EEE;    border1px solid #CCC;    border-radius10px;    positionrelative;    overflowhidden;
}#demo_gesture > #demo_gesture_fore {    color#CCC;    text-aligncenter;    width20px;    height20px;    background-color#CCC;    border-radius10px;    positionabsolute;    top0;    left0;    overflowhidden;    cursorpointer;
}

After document is ready, we can execute following JavaScript.

var adjustPosition = function (ele, x) {    x = (ele.position || 0) + x;    if (< 0)        x = 0;    else if (>        ele.parentElement.offsetWidth        - ele.offsetWidth)        x = ele.parentElement.offsetWidth            - ele.offsetWidth;    ele.style.left = x + "px";    return x;};
addSlide("demo_gesture_fore", {    moving: function (ele, pos) {        adjustPosition(            ele,            pos.x);    },    moveEnd: function (ele, pos) {        ele.position = adjustPosition(            ele,            pos.x);    }});

Now, you can continue to implement lots of components which need sliding by touching or mouse.

Microsoft Translator extension for Edge now available to Windows Insiders

$
0
0

Windows Insiders can now translate foreign language web pages for 50+ languages in the Microsoft Edge browser by downloading the brand new Microsoft Translator Edge extension.

The Microsoft Translator Edge extension is one of the first group of extensions available for preview on Edge to personalize and add new features to the browser. These preview extensions are currently available only to Windows 10 Insider Preview members, and can be used with build 14291 and above.

Once installed, the translation icon will appear in the address bar when visiting a foreign-language webpage in Microsoft Edge. You can then click on the icon to instantly translate the webpage to your current Windows language. The extension works with all of the languages supported by Microsoft Translator.

If you are already a Windows Insider, you can add the extension to Edge by following the steps shown below or in the video above.

  1. Download the extension.
  2. Select Run from the download notification.
  3. From your Edge browser, select More (...) and then Extensions.
  4. Select Load extension, choose the extension folder, then click Select folder.

If you are not currently a Windows Insider, don't worry. When fully released to mainstream builds of Windows 10, the Microsoft Translator extension will be available to the public via the Windows Store. Learn more about the Windows 10 Insider program here.

Be sure to let us know what you think about the new extension on our customer support and feedback page.


Learn more:

JavaScript Promise

$
0
0

In font-end web software development area, I believe you know Promise if you have experience in jQuery, ES6 or Node.js. Promise object is used for deferred and asynchronous computations. It represents following cases.

  • An operation has not completed but we can expect its result.
  • Done with or without a result value.
  • Failed with or without an error reason.
  • Will not turn back the status after it has completed.

But if you were going to implement Promise, how will you do? Today, I will introduce one of the implementation in Type Script for web app. Suppose we will have following scenario.

var promise = new Promise(    function (resolve, reject) {        setTimeout(function () {            var now = new Date();            if (now.getSeconds() % 2 === 0)                resolve(now);            else                reject(now);        }, 1000);    });
promise.then(    function (value) {        console.debug("Success", value);    },    function (reasone) {        console.debug("Error", reasone);    });

The test is very simple. We will run a function asynchronously. A callback registered will be run if the function runs succeeded and another callback will be run if failed. So the class Promise is what we will implement.

Considering there is a Promise in ES6, so we will use a new name LitePromise as its name here. What should be in the class?

  • A constructor which can pass an argument which is a function to run. The function has 2 arguments and both of them are delegates. These delegates are provided by Promise class for using in the function. The first delegate is used to pass a result to handle success callbacks; the other is to pass failure reason to handle fail callbacks.
  • A member method to register on fulfilled callback for success and on rejected callback for failure. This method should return another Promise so that we can register callbacks after this Promise has completed. Both of the callback can pass an argument which is the result or error reason. And both of the callback can return a value as the next Promise result value or failure reason.

So we got following code.

export class LitePromise<T> implements PromiseLike<T> {    public constructor(executor: (        resolve: (value?: T | PromiseLike<T>) => void,        reject: (reason?: any) => void) => void) {        // ToDo: Implement it.    }    public then<TResult>(        onfulfilled?: (value: T) => TResult | PromiseLike<TResult>,        onrejected?: (reason: any) => TResult | PromiseLike<TResult> | void)        : LitePromise<TResult> {        return new LitePromise<TResult>((resolve, reject) => {            // ToDo: Implement it.        })    }    public catch(onrejected?: (reason: any) => T | PromiseLike<T> | void)        : LitePromise<T> {        return this.then(null, onrejected);    }
}

To continue to implement this, we need have some fields to store useful information.

  • A state including pending, success or fail.
  • A value for result or failure reason.

So we have following code.

private _state: boolean = null;private _value: T;

Here, state is null represents it is pending; true is successful; false is failure. Now lets implement resolve method.

  1. Check state. The function should do nothing if the state is pending.
  2. Check if the value is the Promise itself. It forbids for this case.
  3. Set state as success and set the result value.
  4. Handle all deferred information registered.
  5. We also need a try-catch for handle exception. If fails, it need go to reject route.
private _resolve(value: T | PromiseLike<T>) {    if (this._state !== null)        return;    if (value === this)        throw new TypeError('A promise cannot be resolved with itself.');    this._state = true;    this._value = value as T;    // ToDo: Handle all deferred information.
}

And we need add a try-catch for exception during processing this method. It will go to reject route if it fails.

private _resolve(value: T | PromiseLike<T>) {    try {        // Original implementation for resolving.    } catch (e) {        // Reject route.    }
}

However, if the result value is another Promise object, we should raise its callback instead of current logic. So we need add an additional flag indicating this.

private _delegating = false;

And add following logic before set state and value.

if (value    && (typeof value === 'object' || typeof value === 'function')    && typeof (value as PromiseLike<T>).then === "function") {    this._delegating = true;    (value as PromiseLike<T>).then(this._resolve, this._reject);    return;
}

For reject route, we just need check if the state is not in pending and set the state as failure and set the value as the error reason. Then handle all deferred information registered.

private _reject(reason) {    if (this._state !== null)        return    this._state = false;    this._value = reason;    // ToDo: Handle all deferred information.
}

For deferred information, we need save its following things.

  • On fulfilled callback for success.
  • On rejected callback for failure.
  • A resolve handler for next Promise.
  • A reject handler for next Promise.

So it will be as the following interface.

export interface DeferredContract<T, TResult> {    onFulfilled: (value: T) => TResult | PromiseLike<TResult>;    onRejected: (reason: any) => TResult | PromiseLike<TResult> | void;    resolve: (value?: TResult | PromiseLike<TResult>) => void;    reject: (reason?: any) => void;
}

And add a deferred list property in Promise class.

private _deferreds: DeferredContract<T, any>[] = [];

To handle one of deferred information registered, we need check if the state is in pending. If so, we just add it into the list; otherwise, raise callback.

private _handle<TResult>(deferred: DeferredContract<T, TResult>) {    if (this._state === null) {        this._deferreds.push(deferred);        return;    }    setTimeout(() => {        // Raise callback.    }, 0);
}

We can raise callback as following steps.

  1. Check state to determine if it is to raise success callback or failure callback.
  2. Call its resolve delegate or reject delegate if the callback is not set. And then return.
  3. Raise the callback in a try-catch. Go to reject route if fails; otherwise, resolve.

Code is like following.

// Check state.var cb = this._state ? deferred.onFulfilled : deferred.onRejected;if (cb === null) {    // Default callback.    (this._state ? deferred.resolve : deferred.reject)(this._value as any);    return;
}// Callback.var ret: TResult | PromiseLike<TResult>;try {    ret = cb(this._value) as any;
}catch (e) {    deferred.reject(e);    return
}// Resolve.
deferred.resolve(ret)

As what we have discussed before, the member method then which is used to register deferred callbacks will return next Promise. The constructor need pass a function as its argument. The function is to handle the deferred information. So we can implement it there now as following.

this._handle<TResult>({    onFulfilled: onfulfilled,    onRejected: onrejected,    resolve: resolve,    reject: reject
});

Then we need add a method to handle all deferred information and clear after it has completed.

private _finale() {    for (var i = 0, len = this._deferreds.length; i < len; i++)        this._handle(this._deferreds[i]);    this._deferreds = null;
}

The rest thing is to implement the constructor. We just check if the delegating flag is off to resolve result or reject.

try {    executor((value) => {        if (!this._delegating) this._resolve(value)    }, (reason) => {        if (!this._delegating) this._reject(reason)    });
} catch (e) {    if (!this._delegating) this._reject(e)
}

The LitePromise class is done now. So let's continue to implement a helper function. A function is to create a Promise that is resolved with an array of results when all of the provided Promises resolve, or rejected when any Promise is rejected. We need use a counter to check the state for all Promise passed. The Promise returned will resolve when all have completed. It will reject if any of them is not in correct way. Following is the code.

namespace LitePromise {    export function all(values: any[]): LitePromise<any[]> {        var args = Array.prototype.slice.call(arguments.length === 1 && Array.isArray(arguments[0]) ? arguments[0] : arguments)        return new LitePromise<any[]>((resolve, reject) => {            if (args.length === 0return resolve([]);            var remaining = args.length;            var res = (i, value) => {                try {                    // Check if it is a promise.                    if (value && (typeof value === 'object' || typeof value === 'function'&& typeof (value as PromiseLike<any>).then === "function") {                        (value as PromiseLike<any>).then(                            (val) => {                                res(i, val)                            },                            reject);                        return;                    }                    // Simple value.                    args[i] = value;                    // Wait for all.                    if (--remaining === 0) {                        resolve(args);                    }                } catch (ex) {                    reject(ex);                }            }            for (var i = 0; i < args.length; i++) {                res(i, args[i]);            }        });    }
}

For helper function race, which creates a Promise that is resolved or rejected when any of the provided Promises are resolved or rejected, is like the function all, so I will not introduce here.

export function race<T>(values: Iterable<| PromiseLike<T>>): Promise<T> {    // ToDo: Implement it.
}

You can implement it by yourself.

SharePoint 2016 Easter-Eggs - Frohe Ostern

$
0
0

Frohe Ostern alle miteinander!

Zu diesem Fest möchte ich euch ein paar kleinere Funktionen in SharePoint 2016 zeigen, über die bisher noch nicht so intensiv diskutiert wurde - man möchte fast sagen, es gibt ein paar kleine versteckte Ostereier, die wir nun gemeinsamen finden möchten.

1. Automatische QR Codes für SharePoint Objekte

Microsoft hat viel am Look and Feel geschraubt, um den neuen SharePoint auch freundlicher bei mobiler Nutzung zu machen. Es ist dennoch sehr mühsam, sich mit einem Handy oder einem anderem mobilen Gerät, durch die Struktur des SharePoints zu hangeln. In SharePoint 2013 gab es daher schon eine kleine Lösung im Codeplex, die per Click einen  QR Code (Quick Response) erzeugt hat. So ein QR Code ist ein zweidimensionales Muster, das mit einer Handy-App und der Kamera eingescannt wird und normalerweise nach der "Übersetzung" einen Link generiert, der dann direkt zu dem enstsprechenden Objekt navigiert. Eine sehr schöne Erleichterung.

In SharePoint 2016 ist diese kleine aber feine Funktion nun direkt eingebaut und man findet sie im Kontextmenü der entsprechenden Objekte einer Liste oder Bibliothek. Dies hilft sehr, wenn man noch schnell ein Dokument auf dem Handy lesen möchte, aber schon den Arbeitsplatz verlassen muss. In SP2016 ist fix der Code generiert, mit dem Handy eingescannt und schon wird das Dokument mit dem mobilen Gerät geöffnet. Vorraussetzung ist natürlich, ein Handy mit Kamera und entsprechender App (normalerweise standard in fast jedem mobilen Browser). Außerdem muss man sich mit dem Handy im Unternehmensnetzwerk befinden oder der SharePoint bzw. das einzelne Objekt ist auch über das Internet extern zugänglich.

 

2. Einen Ordner erstellen und direkt teilen

Ein weiter Fokus wurde von Microsoft auf die "Moderne Zusammenarbeit" gelegt. Ein Beispiel dafür ist das erstellen eines neuen Ordners in einer Dokumentenbibliothek. Daber können nun direkt Nutzer oder Gruppen mit eingetragen werden, die Zugriff auf diesen Ordner erhalten sollen. Dies reduziert den administrativen Aufwand bei entsprechenden Berechtigungsstrukturen um einige Klicks. Ich finde, auch diese kleine Verbesserung ist gut gelungen.

 

3. Das Pinnen von Seiten

Wir können Seiten folgen - na klar, das ist keine Neuerung! Aber dabei kann auch schnell mal eine recht lange Liste an Seiten zusammen kommen. In SharePoint 2016 hat Microsoft daher eine weitere Option zum "Sortieren" der gefolgten Seiten eingeführt. Man kann nun einzelne Seiten "pinnen", was bedeutet, dass diese Seiten ganz nach oben in der Liste der gefolgten Seiten wandern. Auch eine schöne Funktion, um etwas mehr Übersichtlichkeit da rein zu bringen, was die Social Features unter Umständen unordentlich machen können.

 

Aber nun viel Spaß bei der echten Eiersuche und spätestens ab Dienstag wieder "Happy SharePointing"!

Viewing all 12366 articles
Browse latest View live