<commit_before>// Submote by Zarlach

console.log('Submote has started');

// Global vars
var subMotes    = {};           // subMotes[emote] = source
var subEmotes   = {};           // subEmotes[emote] = id
var bttvEmotes  = {};           // bttvEmotes[emote] = source

// Check if emotes are already stored locally
if (localStorage.getItem("subEmotes") === null)
    loadSubEmotes();
else
{
    subEmotes           = JSON.parse(localStorage.getItem("subEmotes"));
    var genDate         = Date.parse(subEmotes['generated_at']);
    var currentDate     = new Date();
    var expirationDate  = genDate+3600*1000/2;  //30 minutes

    //Check if expired
    if(currentDate.getTime() >= expirationDate)
        loadSubEmotes();
}

if (localStorage.getItem("bttvEmotes") === null)
    loadBetterTTVemotes();
else{
    bttvEmotes = JSON.parse(localStorage.getItem("bttvEmotes"));

    // Custom BetterTTV Emotes
    bttvEmotes['PepePls'] = 'https://cdn.betterttv.net/emote/55898e122612142e6aaa935b/1x';
    bttvEmotes['(ditto)'] = 'https://cdn.betterttv.net/emote/554da1a289d53f2d12781907/1x';
}

/**
 * Check for new chat messages
 */
$(document).read(function(){
    $('.chat-lines').on('DOMNodeInserted', function(e)
    {
        console.log('Detected new message');
        var element = e.target;
        var line    = $(element).last();

        // Extensions
        var ffz  = false;
        var bttv = false;

        // Usually, chat messages are called 'chat-line' (class)
        if($('li.chat-line').length){
            line = $('.chat-line').last();
            console.log(line.attr('data-sender'));
        }

        //Check if it's a message
        if (line.last().length
            && line.find('.message').last().html() !== undefined
            && line.not('.admin'))
        {
            var message = line.find('.message').last();
            var badges  = line.find('.badges');
            var from    = line.find('.from').html().toLowerCase();

            //Parse message
            if(from !== 'jtv') {
                parseMessage(message, subEmotes);
                parseMessage(message, bttvEmotes);
            }

            //Append turbo
            if(from === 'zarlach' && badges.last().find('.submote-dev').length === 0) {
                $(badges).last().append('

');
                $(badges).last().find('.submote-dev').css({
                    'width': '18px',
                    'height': '18px',
                    'background-image': 'url(https://cdn.rawgit.com/Zarlach/Submote/master/images/dev-badge.png)',
                    'background-repat': 'no-repeat',
                    'background-size': '18px 18px'
                });
            }
        }
    });
});

/**
 * Load subscriber emotes from web
 */
function loadSubEmotes()
{
    $.getJSON('https:twitchemotes.com/api_cache/v2/subscriber.json', function(data)
    {
        $.each(data['channels'], function(channel, properties)
        {
            $.each(properties['emotes'], function(list, emote){
                subEmotes[emote['code']] = emote['image_id'];
            });
        });

        $.each(data['meta'], function(key, val){
            subEmotes[key] = val;
        });
    })
    .done(function()
    {
        subEmotes['provider'] = 'twitch';
        localStorage.setItem("subEmotes", JSON.stringify(subEmotes));
    })
    .fail(function()
    {
        //sendError('Submote could not load sub emotes');
        console.log('Could not load sub emotes');
    });
}

/**
 * Load BetterTTV emotes from web
 */
function loadBetterTTVemotes()
{
    $.getJSON('https://cdn.betterttv.net/emotes/emotes.json', function(data){
        $.each(data, function(key, value){
            bttvEmotes[value['regex'].replace('\\', '')] = value['url'].replace('//', 'https://');
        });
    })
    .done(function(){
        bttvEmotes['provider'] = 'betterttv';
        localStorage.setItem("bttvEmotes", JSON.stringify(bttvEmotes));
    })
    .fail(function(){
        console.log('Submote could not load BetterTTV emotes');
    });
}

/**
 * Scan message and replace words with emotes!
 *
 * @param  {element} ele        Message element
 * @param  {object} list        List of emotes
 * @param  {string} provider    Emote provider
 */
function parseMessage(ele, list)
{
    var msg         = ele.html();
    var split       = msg.replace(/(<([^>]+)>)/ig,'').trim().split(' ');
        split       = $.grep(split,function(n){ return(n) });
    var words       = [];
    var provider    = list['provider'];
    var regex;
    var word;

    //Remove duplicates
    $.each(split, function(i, el){
        if($.inArray(el, words) === -1) words.push(el);
    });

    //
    for (var i = 0; i <= words.length; i++) {
        word = words[i];

        if(validateFilter(word, list, provider))
        {
            regex = new RegExp('\\b'+word+'\\b(?=[^"]*(?:"[^"]*"[^"]*)*$)', 'g');
            msg = msg.replace(regex, generateEmoteImage(word, list[word], provider));
        }
    }

    ele.html(msg.trim());
}

/**
 * Generate emote image HTML tag.
 *
 * @param  {int} id Emote ID
 * @return {string}    HTML img tag
 */
function generateEmoteImage(emote, source, provider)
{
    switch(provider){
        case 'twitch':
            return '';
            break;
        case 'betterttv':
            return '';
            break;
    }
}

/**
 * Run selected word through a filter
 *
 * @param  {string}     word     Selected word
 * @param  {object}     list     Emote list
 * @param  {string}     provider Emote provider
 * @return {boolean}    Returns whether or not the word passed the filter
 */
function validateFilter(word, list, provider)
{
    var regex = new RegExp('^(?=.*[a-z])(?=.*[A-Z]).+$');

    //General filter
    if(list[word] === undefined
        || !regex.test(word)
        || word === 'provider'
        || word === 'generated_at'
        || word.length === 0)
        return false;

    //Provider specific filter
    switch(provider){
        case 'twitch':
            if (word[0] !== word[0].toLowerCase()
                || word === 'double'
                || word === 'triple'
                || word === 'quadra'
                || word === 'penta'
                || word === 'kill'
                || word === 'snap')
                return false;

            break;
        case 'betterttv':

            break;
    }

    return true;
}

/**
 * In case something fails, let the user know!
 *
 * @param  {string} message Error description
 */
function sendError(message)
{
    $('body').append('

'+message+'
Please refresh

');
}<commit_msg>Nobody saw that<commit_after>// Submote by Zarlach

console.log('Submote has started');

// Global vars
var subMotes    = {};           // subMotes[emote] = source
var subEmotes   = {};           // subEmotes[emote] = id
var bttvEmotes  = {};           // bttvEmotes[emote] = source

// Check if emotes are already stored locally
if (localStorage.getItem("subEmotes") === null)
    loadSubEmotes();
else
{
    subEmotes           = JSON.parse(localStorage.getItem("subEmotes"));
    var genDate         = Date.parse(subEmotes['generated_at']);
    var currentDate     = new Date();
    var expirationDate  = genDate+3600*1000/2;  //30 minutes

    //Check if expired
    if(currentDate.getTime() >= expirationDate)
        loadSubEmotes();
}

if (localStorage.getItem("bttvEmotes") === null)
    loadBetterTTVemotes();
else{
    bttvEmotes = JSON.parse(localStorage.getItem("bttvEmotes"));

    // Custom BetterTTV Emotes
    bttvEmotes['PepePls'] = 'https://cdn.betterttv.net/emote/55898e122612142e6aaa935b/1x';
    bttvEmotes['(ditto)'] = 'https://cdn.betterttv.net/emote/554da1a289d53f2d12781907/1x';
}

/**
 * Check for new chat messages
 */
$(document).ready(function(){
    $('.chat-lines').on('DOMNodeInserted', function(e)
    {
        console.log('Detected new message');
        var element = e.target;
        var line    = $(element).last();

        // Extensions
        var ffz  = false;
        var bttv = false;

        // Usually, chat messages are called 'chat-line' (class)
        if($('li.chat-line').length){
            line = $('.chat-line').last();
            console.log(line.attr('data-sender'));
        }

        //Check if it's a message
        if (line.last().length
            && line.find('.message').last().html() !== undefined
            && line.not('.admin'))
        {
            var message = line.find('.message').last();
            var badges  = line.find('.badges');
            var from    = line.find('.from').html().toLowerCase();

            //Parse message
            if(from !== 'jtv') {
                parseMessage(message, subEmotes);
                parseMessage(message, bttvEmotes);
            }

            //Append turbo
            if(from === 'zarlach' && badges.last().find('.submote-dev').length === 0) {
                $(badges).last().append('

');
                $(badges).last().find('.submote-dev').css({
                    'width': '18px',
                    'height': '18px',
                    'background-image': 'url(https://cdn.rawgit.com/Zarlach/Submote/master/images/dev-badge.png)',
                    'background-repat': 'no-repeat',
                    'background-size': '18px 18px'
                });
            }
        }
    });
});

/**
 * Load subscriber emotes from web
 */
function loadSubEmotes()
{
    $.getJSON('https:twitchemotes.com/api_cache/v2/subscriber.json', function(data)
    {
        $.each(data['channels'], function(channel, properties)
        {
            $.each(properties['emotes'], function(list, emote){
                subEmotes[emote['code']] = emote['image_id'];
            });
        });

        $.each(data['meta'], function(key, val){
            subEmotes[key] = val;
        });
    })
    .done(function()
    {
        subEmotes['provider'] = 'twitch';
        localStorage.setItem("subEmotes", JSON.stringify(subEmotes));
    })
    .fail(function()
    {
        //sendError('Submote could not load sub emotes');
        console.log('Could not load sub emotes');
    });
}

/**
 * Load BetterTTV emotes from web
 */
function loadBetterTTVemotes()
{
    $.getJSON('https://cdn.betterttv.net/emotes/emotes.json', function(data){
        $.each(data, function(key, value){
            bttvEmotes[value['regex'].replace('\\', '')] = value['url'].replace('//', 'https://');
        });
    })
    .done(function(){
        bttvEmotes['provider'] = 'betterttv';
        localStorage.setItem("bttvEmotes", JSON.stringify(bttvEmotes));
    })
    .fail(function(){
        console.log('Submote could not load BetterTTV emotes');
    });
}

/**
 * Scan message and replace words with emotes!
 *
 * @param  {element} ele        Message element
 * @param  {object} list        List of emotes
 * @param  {string} provider    Emote provider
 */
function parseMessage(ele, list)
{
    var msg         = ele.html();
    var split       = msg.replace(/(<([^>]+)>)/ig,'').trim().split(' ');
        split       = $.grep(split,function(n){ return(n) });
    var words       = [];
    var provider    = list['provider'];
    var regex;
    var word;

    //Remove duplicates
    $.each(split, function(i, el){
        if($.inArray(el, words) === -1) words.push(el);
    });

    //
    for (var i = 0; i <= words.length; i++) {
        word = words[i];

        if(validateFilter(word, list, provider))
        {
            regex = new RegExp('\\b'+word+'\\b(?=[^"]*(?:"[^"]*"[^"]*)*$)', 'g');
            msg = msg.replace(regex, generateEmoteImage(word, list[word], provider));
        }
    }

    ele.html(msg.trim());
}

/**
 * Generate emote image HTML tag.
 *
 * @param  {int} id Emote ID
 * @return {string}    HTML img tag
 */
function generateEmoteImage(emote, source, provider)
{
    switch(provider){
        case 'twitch':
            return '';
            break;
        case 'betterttv':
            return '';
            break;
    }
}

/**
 * Run selected word through a filter
 *
 * @param  {string}     word     Selected word
 * @param  {object}     list     Emote list
 * @param  {string}     provider Emote provider
 * @return {boolean}    Returns whether or not the word passed the filter
 */
function validateFilter(word, list, provider)
{
    var regex = new RegExp('^(?=.*[a-z])(?=.*[A-Z]).+$');

    //General filter
    if(list[word] === undefined
        || !regex.test(word)
        || word === 'provider'
        || word === 'generated_at'
        || word.length === 0)
        return false;

    //Provider specific filter
    switch(provider){
        case 'twitch':
            if (word[0] !== word[0].toLowerCase()
                || word === 'double'
                || word === 'triple'
                || word === 'quadra'
                || word === 'penta'
                || word === 'kill'
                || word === 'snap')
                return false;

            break;
        case 'betterttv':

            break;
    }

    return true;
}

/**
 * In case something fails, let the user know!
 *
 * @param  {string} message Error description
 */
function sendError(message)
{
    $('body').append('

'+message+'
Please refresh

');
}<|endoftext|>


<commit_before>
<commit_msg>FIX: Deleted devtest<commit_after><|endoftext|>


<commit_before>console.log('App works!');
var config = {
    'first_name': 'Derpington', // Shipping firstname
    'last_name': 'McYeezus', // Shipping surname
    'street_address_1': '2 Supreme St.', // main address for shipping address
    'street_address_2': 'Suite 6', // used for apartment #s, etc FOR SHIPPING
    'city': 'New York', // City for shipping information
    'state': 'New York', // State for shipping information
    'zipcode': '10013', // ZIP CODE for shipping information
    'phone_number': 'XXX-XXX-XXXX', // must be in this format
    'billing_address_1': '300 Supreme St', // main address for billing address
    'billing_address_2': '', // used for apartment #s, etc for BILLING
    'billing_city': 'Los Angeles', // City for billing information
    'billing_state': 'California', // State for billing information
    'billing_zipcode': '90036', // ZIP CODE for billing information
    'name_on_card': 'Hypebeast McSupreme', //FULL NAME as printed on the front of your Credit Card
    'card_number': 'STEALMYIDENTITY101', // Put your full Credit Card # in this field without spaces or dashes or anything
    'expires_month': 'January', // must be full month name to match adidas.com
    'expires_year': '2001', // Year the Credit Card expires
    'security_code': '404', // a 3 or 4 digit CVV code that is on the back of your Credit Card (4 Digits for AMEX on front)
};
var urlCheck = urlChecker();
function urlChecker() {
    console.log('checking page');
    var primeUrl = 'http://www.supremenewyork.com/shop/new';
    var lastUrl = window.location.href;

    window.urlChecker = setInterval(function() {
        console.log(primeUrl);
        console.log(lastUrl);
        if (primeUrl === lastUrl) {
            console.log('found the right one!');
        }

        if (lastUrl !== window.location.href) {
            lastUrl = window.location.href;
            checkPage();
        }
    }, 500);
}
function checkPage() {
    console.log('CHECKING PAGE!');

    // on the product landing page, try to cop in our size
    if ($('div#productInfo').length) {
        lookForSizes();
    }
    // on the cart page! smash that checkout button
    else if (window.location.href.indexOf('Cart-Show') > -1) {
        $('button[name=dwfrm_cart_checkoutCart]').trigger('click');
    }
    // we're shipping.. lets make sure info is correct
    else if (window.location.href.indexOf('delivery-start') > -1) {
        addShipping();
    }
    // bruh we're so close. please.
    else if ($('li.active.step-2').length) {
        pay();
    }
    // keep trying if nothing
    else {
        setTimeout(function() {
            checkPage();
        }, 1000);
    }
}
<commit_msg>Item navigation<commit_after>console.log('App works!');
var config = {
    'first_name': 'Derpington', // Shipping firstname
    'last_name': 'McYeezus', // Shipping surname
    'street_address_1': '2 Supreme St.', // main address for shipping address
    'street_address_2': 'Suite 6', // used for apartment #s, etc FOR SHIPPING
    'city': 'New York', // City for shipping information
    'state': 'New York', // State for shipping information
    'zipcode': '10013', // ZIP CODE for shipping information
    'phone_number': 'XXX-XXX-XXXX', // must be in this format
    'billing_address_1': '300 Supreme St', // main address for billing address
    'billing_address_2': '', // used for apartment #s, etc for BILLING
    'billing_city': 'Los Angeles', // City for billing information
    'billing_state': 'California', // State for billing information
    'billing_zipcode': '90036', // ZIP CODE for billing information
    'name_on_card': 'Hypebeast McSupreme', //FULL NAME as printed on the front of your Credit Card
    'card_number': 'STEALMYIDENTITY101', // Put your full Credit Card # in this field without spaces or dashes or anything
    'expires_month': 'January', // must be full month name to match adidas.com
    'expires_year': '2001', // Year the Credit Card expires
    'security_code': '404', // a 3 or 4 digit CVV code that is on the back of your Credit Card (4 Digits for AMEX on front)
    'item_names': ['tshirt', 'rosejacket'],
};
var primeUrl = 'http://www.supremenewyork.com/shop/new';
var urlCheck = urlChecker();
function urlChecker() {
    var lastUrl = window.location.href;

    window.urlChecker = setInterval(function() {
        console.log(primeUrl);
        console.log(lastUrl);
        if (primeUrl === lastUrl) {
            stopUrl();
            findItem();
        }
        window.location.href = primeUrl;
    }, 500);
}

function stopUrl() {
    clearInterval(window.urlChecker);
}

function findItem() {
        var count = Math.floor(Math.random() * $('article').length);
        var accessUrl = $('article:eq( ' + count + ' )').find('a').attr('href');
        window.location.href = accessUrl;
        for (var j in config.item_names) {
            if ($('h1')[1].text().toLowerCase().includes(config.item_names[j])) {
                console.log('We got the right item!');
            } else {
                console.log('Not the right item');
                window.location.href = primeUrl;
            }
        }
}

function checkPage() {
    console.log('CHECKING PAGE!');

    // on the product landing page, try to cop in our size
    if ($('div#productInfo').length) {
        lookForSizes();
    }
    // on the cart page! smash that checkout button
    else if (window.location.href.indexOf('Cart-Show') > -1) {
        $('button[name=dwfrm_cart_checkoutCart]').trigger('click');
    }
    // we're shipping.. lets make sure info is correct
    else if (window.location.href.indexOf('delivery-start') > -1) {
        addShipping();
    }
    // bruh we're so close. please.
    else if ($('li.active.step-2').length) {
        pay();
    }
    // keep trying if nothing
    else {
        setTimeout(function() {
            checkPage();
        }, 1000);
    }
}
<|endoftext|>


<commit_before>var Swapper = function (window, document, Zepto, jQuery) {
	var NO_TRANSFORM = 'translate3d(0,0,0) scale(1)';

	var transitions = {
			'fade' : [
				{ fade : true },
				{ fade : true }
			],
			'fade-on' : [
				{ fade : true },
				{}
			],
			'fade-off' : [
				{},
				{ fade : true },
				true
			],
			'scale-in' : [
				{ transform : 'scale(0.01)' },
				{}
			],
			'scale-out' : [
				{},
				{ transform : 'scale(0.01)' },
				true
			],
			'rotate-left' : [
				{ transform : 'rotateY(-180deg) perspective(360px)' , fade : true },
				{ transform : 'rotateY( 180deg) perspective(360px)' , fade : true }
			],
			'rotate-right' : [
				{ transform : 'rotateY( 180deg) perspective(360px)' , fade : true },
				{ transform : 'rotateY(-180deg) perspective(360px)' , fade : true }
			],
			'cube-left' : [
				{ transform : 'translate3d( 50%,0,0) rotateY(-90deg) perspective(360px)' },
				{ transform : 'translate3d(-50%,0,0) rotateY( 90deg) perspective(360px)' }
			],
			'cube-right' : [
				{ transform : 'translate3d(-50%,0,0) rotateY( 90deg) perspective(360px)' },
				{ transform : 'translate3d( 50%,0,0) rotateY(-90deg) perspective(360px)' }
			],
			'swap-left' : [
				{ transform : 'translate3d( 65%,0,0) rotateY( 90deg) perspective(360px)' },
				{ transform : 'translate3d(-65%,0,0) rotateY(-90deg) perspective(360px)' }
			],
			'swap-right' : [
				{ transform : 'translate3d(-65%,0,0) rotateY(-90deg) perspective(360px)' },
				{ transform : 'translate3d( 65%,0,0) rotateY( 90deg) perspective(360px)' }
			],
			'explode-in' : [
				{ fade : true , transform : 'scale(1.25)' },
				{}
			],
			'explode-out' : [
				{},
				{ fade : true , transform : 'scale(1.25)' },
				true
			],
			'implode-in' : [
				{},
				{ fade : true , transform : 'scale(0.60)' },
				true
			],
			'implode-out' : [
				{ fade : true , transform : 'scale(0.80)' },
				{}
			],
			'slide-left' : [
				{ transform : 'translate3d( 100%,0,0)' },
				{ transform : 'translate3d(-100%,0,0)' }
			],
			'slide-right' : [
				{ transform : 'translate3d(-100%,0,0)' },
				{ transform : 'translate3d( 100%,0,0)' }
			],
			'slide-up' : [
				{ transform : 'translate3d(0, 100%,0)' },
				{ transform : 'translate3d(0,-100%,0)' }
			],
			'slide-down' : [
				{ transform : 'translate3d(0,-100%,0)' },
				{ transform : 'translate3d(0, 100%,0)' }
			],
			'slideon-left' : [
				{ transform : 'translate3d(-100%,0,0)' },
				{}
			],
			'slideoff-left' : [
				{},
				{ transform : 'translate3d(-100%,0,0)' },
				true
			],
			'slideon-right' : [
				{ transform : 'translate3d(100%,0,0)' },
				{}
			],
			'slideoff-right' : [
				{},
				{ transform : 'translate3d(100%,0,0)' },
				true
			],
			'slideon-up' : [
				{ transform : 'translate3d(0,-100%,0)' },
				{}
			],
			'slideoff-up' : [
				{},
				{ transform : 'translate3d(0,-100%,0)' },
				true
			],
			'slideon-down' : [
				{ transform : 'translate3d(0,100%,0)' },
				{}
			],
			'slideoff-down' : [
				{},
				{ transform : 'translate3d(0,100%,0)' },
				true
			]
		},
		easings     = {
			'linear'      : 'linear'      ,
			'ease'        : 'ease'        ,
			'ease-in'     : 'ease-in'     ,
			'ease-out'    : 'ease-out'    ,
			'ease-in-out' : 'ease-in-out' ,
			'step-start'  : 'step-start'  ,
			'step-end'    : 'step-end'
		};

	function isNode (elem) {
		if ( !elem ) {
			return false;
		}

		try {
			return (elem instanceof Node) || (elem instanceof HTMLElement);
		} catch (err) {}

		if (typeof elem !== 'object') {
			return false;
		}

		if (typeof elem.nodeType !== 'number') {
			return false;
		}

		if (typeof elem.nodeName !== 'string') {
			return false;
		}

		return true;
	}

	function isInDOM (elem, skipNodeCheck) {
		if (!skipNodeCheck && !isNode(elem)) {
			throw TypeError('element must be a DOM node, got ' + elem);
		}

		while (elem = elem.parentNode) {
			if (elem === document) {
				return true;
			}
		}

		return false;
	}

	function insertBefore (newElem, targetElem) {
		targetElem.parentNode.insertBefore(newElem, targetElem);
	}

	function insertAfter (newElem, targetElem) {
		var parent = targetElem.parentNode;

		if (parent.lastchild === targetElem) {
			parent.appendChild(newElem);
		}
		else {
			parent.insertBefore(newElem, targetElem.nextSibling);
		}
	}

	function removeNode (elem) {
		if (elem.parentNode) {
			elem.parentNode.removeChild(elem);
		}
	}

	function setTransform (elem, transform) {
		elem.style['-webkit-transform'] = transform;
		elem.style[   '-moz-transform'] = transform;
		elem.style[    '-ms-transform'] = transform;
		elem.style[     '-o-transform'] = transform;
		elem.style[        'transform'] = transform;
	}

	function setTransition (elem, transition) {
		if (transition) {
			elem.style['-webkit-transition'] = '-webkit-'+transition;
			elem.style[   '-moz-transition'] =    '-moz-'+transition;
			elem.style[    '-ms-transition'] =     '-ms-'+transition;
			elem.style[     '-o-transition'] =      '-o-'+transition;
			elem.style[        'transition'] =            transition;
		}
		else {
			elem.style['-webkit-transition'] = '';
			elem.style[   '-moz-transition'] = '';
			elem.style[    '-ms-transition'] = '';
			elem.style[     '-o-transition'] = '';
			elem.style[        'transition'] = '';
		}
	}

	function getStyles (elem, notComputed) {
		var styles;

		if (notComputed) {
			styles = elem.style;
		}
		else {
			styles = document.defaultView.getComputedStyle(elem, null);
		}

		return {
			display  : styles.display  ,
			opacity  : styles.opacity  ,
			top      : styles.top      ,
			left     : styles.left     ,
			height   : styles.height   ,
			width    : styles.width    ,
			position : styles.position
		};
	}

	function validateElement (elem) {
		if ( !isNode(elem) ) {
			throw TypeError('element must be a DOM node, got ' + elem);
		}
	}

	function validateOptions (options) {
		switch (typeof options) {
			case 'string':
				options = { transition: options };
				break;

			case 'undefined':
				options = {};
				break;

			case 'object':
				break;

			default:
				throw TypeError('options must be an object if defined, got ' + options);
		}

		switch (typeof options.transition) {
			case 'string':
				if (!(options.transition in transitions) && (options.transition !== 'instant')) {
					throw TypeError(options.transition + ' is not a valid transition');
				}
				break;

			case 'undefined':
				break;

			default:
				throw TypeError('transition must be a string if defined, got ' + options.transition);
		}

		switch (typeof options.duration) {
			case 'number':
				if (options.duration < 0) {
					throw TypeError('duration must be a non-negative integer, got ' + options.duration);
				}
				break;

			case 'undefined':
				break;

			default:
				throw TypeError('duration must be a number if defined, got ' + options.duration);
		}

		switch (typeof options.easing) {
			case 'string':
				if ( !(options.easing in easings) ) {
					throw TypeError(options.easing + ' is not a valid easing');
				}
				break;

			case 'undefined':
				break;

			default:
				throw TypeError('easing must be a string if defined, got ' + options.easing);
		}

		return options;
	}

	function validateCallback (callback) {
		switch (typeof callback) {
			case 'undefined':
				callback = function () {};
				break;

			case 'function':
				break;

			default:
				throw TypeError('callback must be a function if defined, got ' + callback);
		}

		return callback;
	}

	function swapper (elem1, elem2, options, callback) {
		validateElement(elem1);
		validateElement(elem2);

		if (typeof options === 'function') {
			callback = options;
			options  = {};
		}

		options  = validateOptions(options);
		callback = validateCallback(callback);

		if (elem1._swapper) {
			throw Error('elem1 is currently being swapped');
		}

		if (elem2._swapper) {
			throw Error('elem2 is currently being swapped');
		}

		if ( !isInDOM(elem1, true) ) {
			throw Error('elem1 must be in the DOM to be swapped');
		}

		elem1._swapper = true;
		elem2._swapper = true;

		removeNode(elem2);

		if (options.transition === 'instant') {
			insertAfter(elem2, elem1);
			removeNode(elem1);
			elem1._swapper = false;
			elem2._swapper = false;
			setTimeout(function () {
				callback();
			}, 0);
			return;
		}

		var transition = transitions[options.transition || 'fade'],
			easing     = easings[options.easing || 'ease-in-out'],
			duration   = options.duration || 300;

		insertAfter(elem2, elem1);

		var bounds          = elem1.getBoundingClientRect(),
			computedStyles1 = getStyles(elem1),
			computedStyles2 = getStyles(elem2),
			styles1         = getStyles(elem1, true),
			styles2         = getStyles(elem2, true);

		if (computedStyles1.display !== 'none') {
			elem2.style.position = 'fixed';
			elem2.style.top      = bounds.top  + 'px';
			elem2.style.left     = bounds.left + 'px';
		}
		elem2.style.height   = computedStyles2.height || computedStyles1.height;
		elem2.style.width    = computedStyles2.width  || computedStyles1.width;

		if ( transition[2] ) {
			insertBefore(elem2, elem1);
		}

		setTransform(elem1, NO_TRANSFORM );
		setTransform(elem2, transition[0].transform || NO_TRANSFORM);

		if ( transition[0].fade ) {
			elem2.style.opacity = '0';
		}

		if ( transition[1].fade ) {
			elem1.style.opacity = '1';
		}

		setTimeout(function () {
			var cssTransition = 'transform '+(duration/1000)+'s '+easing+', opacity '+(duration/1000)+'s '+easing;
			setTransition(elem1, cssTransition);
			setTransition(elem2, cssTransition);

			setTimeout(function () {
				setTransform(elem1, transition[1].transform || NO_TRANSFORM);
				setTransform(elem2, NO_TRANSFORM );

				if ( transition[0].fade ) {
					elem2.style.opacity = '1';
				}

				if ( transition[1].fade ) {
					elem1.style.opacity = '0';
				}

				bindCleanup();
				setTimeout(cleanupElems, duration + 300);
			}, 0);
		}, 0);

		var cleanUpLock = false;

		function bindCleanup () {
			elem2.addEventListener('webkitTransitionEnd' , cleanupElems , false);
			elem2.addEventListener('transitionend'       , cleanupElems , false);
			elem2.addEventListener('oTransitionEnd'      , cleanupElems , false);
			elem2.addEventListener('otransitionend'      , cleanupElems , false);
			elem2.addEventListener('MSTransitionEnd'     , cleanupElems , false);
			elem2.addEventListener('transitionend'       , cleanupElems , false);
		}

		function unbindCleanup () {
			elem2.removeEventListener('webkitTransitionEnd' , cleanupElems);
			elem2.removeEventListener('transitionend'       , cleanupElems);
			elem2.removeEventListener('oTransitionEnd'      , cleanupElems);
			elem2.removeEventListener('otransitionend'      , cleanupElems);
			elem2.removeEventListener('MSTransitionEnd'     , cleanupElems);
			elem2.removeEventListener('transitionend'       , cleanupElems);
		}

		function cleanupElems () {
			if (cleanUpLock) {
				return;
			}
			cleanUpLock = true;

			unbindCleanup();

			removeNode(elem1);

			setTransition(elem1, '');
			setTransition(elem2, '');

			setTimeout(function () {
				setTransform(elem1, '');
				setTransform(elem2, '');

				if ( transition[0].fade ) {
					elem2.style.opacity = styles2.opacity;
				}

				if ( transition[1].fade ) {
					elem1.style.opacity = styles1.opacity;
				}

				elem2.style.position = styles2.position;
				elem2.style.top      = styles2.top;
				elem2.style.left     = styles2.left;
				elem2.style.height   = styles2.height;
				elem2.style.width    = styles2.width;

				elem1._swapper = false;
				elem2._swapper = false;

				callback();
			}, 0);
		}
	}

	if (Zepto) {
		Zepto.extend(Zepto.fn, {
			swapper : function (elem2, options, callback) {
				elem2 = Zepto(elem2)[0];

				this.forEach(function (elem1) {
					swapper(elem1, elem2, options, callback);
				});

				return this;
			}
		});
	}

	if (jQuery) {
		jQuery.fn.swapper = function (elem2, options, callback) {
			elem2 = jQuery(elem2)[0];

			this.each(function () {
				swapper(this, elem2, options, callback);
			});

			return this;
		};
	}

	return swapper;
}(window, document, window.Zepto, window.jQuery);
<commit_msg>duration hack only on android<commit_after>var Swapper = function (window, document, Zepto, jQuery) {
	var NO_TRANSFORM = 'translate3d(0,0,0) scale(1)',
		IS_ANDROID   = /\bandroid\b/i.test(navigator.userAgent);

	var transitions = {
			'fade' : [
				{ fade : true },
				{ fade : true }
			],
			'fade-on' : [
				{ fade : true },
				{}
			],
			'fade-off' : [
				{},
				{ fade : true },
				true
			],
			'scale-in' : [
				{ transform : 'scale(0.01)' },
				{}
			],
			'scale-out' : [
				{},
				{ transform : 'scale(0.01)' },
				true
			],
			'rotate-left' : [
				{ transform : 'rotateY(-180deg) perspective(360px)' , fade : true },
				{ transform : 'rotateY( 180deg) perspective(360px)' , fade : true }
			],
			'rotate-right' : [
				{ transform : 'rotateY( 180deg) perspective(360px)' , fade : true },
				{ transform : 'rotateY(-180deg) perspective(360px)' , fade : true }
			],
			'cube-left' : [
				{ transform : 'translate3d( 50%,0,0) rotateY(-90deg) perspective(360px)' },
				{ transform : 'translate3d(-50%,0,0) rotateY( 90deg) perspective(360px)' }
			],
			'cube-right' : [
				{ transform : 'translate3d(-50%,0,0) rotateY( 90deg) perspective(360px)' },
				{ transform : 'translate3d( 50%,0,0) rotateY(-90deg) perspective(360px)' }
			],
			'swap-left' : [
				{ transform : 'translate3d( 65%,0,0) rotateY( 90deg) perspective(360px)' },
				{ transform : 'translate3d(-65%,0,0) rotateY(-90deg) perspective(360px)' }
			],
			'swap-right' : [
				{ transform : 'translate3d(-65%,0,0) rotateY(-90deg) perspective(360px)' },
				{ transform : 'translate3d( 65%,0,0) rotateY( 90deg) perspective(360px)' }
			],
			'explode-in' : [
				{ fade : true , transform : 'scale(1.25)' },
				{}
			],
			'explode-out' : [
				{},
				{ fade : true , transform : 'scale(1.25)' },
				true
			],
			'implode-in' : [
				{},
				{ fade : true , transform : 'scale(0.60)' },
				true
			],
			'implode-out' : [
				{ fade : true , transform : 'scale(0.80)' },
				{}
			],
			'slide-left' : [
				{ transform : 'translate3d( 100%,0,0)' },
				{ transform : 'translate3d(-100%,0,0)' }
			],
			'slide-right' : [
				{ transform : 'translate3d(-100%,0,0)' },
				{ transform : 'translate3d( 100%,0,0)' }
			],
			'slide-up' : [
				{ transform : 'translate3d(0, 100%,0)' },
				{ transform : 'translate3d(0,-100%,0)' }
			],
			'slide-down' : [
				{ transform : 'translate3d(0,-100%,0)' },
				{ transform : 'translate3d(0, 100%,0)' }
			],
			'slideon-left' : [
				{ transform : 'translate3d(-100%,0,0)' },
				{}
			],
			'slideoff-left' : [
				{},
				{ transform : 'translate3d(-100%,0,0)' },
				true
			],
			'slideon-right' : [
				{ transform : 'translate3d(100%,0,0)' },
				{}
			],
			'slideoff-right' : [
				{},
				{ transform : 'translate3d(100%,0,0)' },
				true
			],
			'slideon-up' : [
				{ transform : 'translate3d(0,-100%,0)' },
				{}
			],
			'slideoff-up' : [
				{},
				{ transform : 'translate3d(0,-100%,0)' },
				true
			],
			'slideon-down' : [
				{ transform : 'translate3d(0,100%,0)' },
				{}
			],
			'slideoff-down' : [
				{},
				{ transform : 'translate3d(0,100%,0)' },
				true
			]
		},
		easings     = {
			'linear'      : 'linear'      ,
			'ease'        : 'ease'        ,
			'ease-in'     : 'ease-in'     ,
			'ease-out'    : 'ease-out'    ,
			'ease-in-out' : 'ease-in-out' ,
			'step-start'  : 'step-start'  ,
			'step-end'    : 'step-end'
		};

	function isNode (elem) {
		if ( !elem ) {
			return false;
		}

		try {
			return (elem instanceof Node) || (elem instanceof HTMLElement);
		} catch (err) {}

		if (typeof elem !== 'object') {
			return false;
		}

		if (typeof elem.nodeType !== 'number') {
			return false;
		}

		if (typeof elem.nodeName !== 'string') {
			return false;
		}

		return true;
	}

	function isInDOM (elem, skipNodeCheck) {
		if (!skipNodeCheck && !isNode(elem)) {
			throw TypeError('element must be a DOM node, got ' + elem);
		}

		while (elem = elem.parentNode) {
			if (elem === document) {
				return true;
			}
		}

		return false;
	}

	function insertBefore (newElem, targetElem) {
		targetElem.parentNode.insertBefore(newElem, targetElem);
	}

	function insertAfter (newElem, targetElem) {
		var parent = targetElem.parentNode;

		if (parent.lastchild === targetElem) {
			parent.appendChild(newElem);
		}
		else {
			parent.insertBefore(newElem, targetElem.nextSibling);
		}
	}

	function removeNode (elem) {
		if (elem.parentNode) {
			elem.parentNode.removeChild(elem);
		}
	}

	function setTransform (elem, transform) {
		elem.style['-webkit-transform'] = transform;
		elem.style[   '-moz-transform'] = transform;
		elem.style[    '-ms-transform'] = transform;
		elem.style[     '-o-transform'] = transform;
		elem.style[        'transform'] = transform;
	}

	function setTransition (elem, transition) {
		if (transition) {
			elem.style['-webkit-transition'] = '-webkit-'+transition;
			elem.style[   '-moz-transition'] =    '-moz-'+transition;
			elem.style[    '-ms-transition'] =     '-ms-'+transition;
			elem.style[     '-o-transition'] =      '-o-'+transition;
			elem.style[        'transition'] =            transition;
		}
		else {
			elem.style['-webkit-transition'] = '';
			elem.style[   '-moz-transition'] = '';
			elem.style[    '-ms-transition'] = '';
			elem.style[     '-o-transition'] = '';
			elem.style[        'transition'] = '';
		}
	}

	function getStyles (elem, notComputed) {
		var styles;

		if (notComputed) {
			styles = elem.style;
		}
		else {
			styles = document.defaultView.getComputedStyle(elem, null);
		}

		return {
			display  : styles.display  ,
			opacity  : styles.opacity  ,
			top      : styles.top      ,
			left     : styles.left     ,
			height   : styles.height   ,
			width    : styles.width    ,
			position : styles.position
		};
	}

	function validateElement (elem) {
		if ( !isNode(elem) ) {
			throw TypeError('element must be a DOM node, got ' + elem);
		}
	}

	function validateOptions (options) {
		switch (typeof options) {
			case 'string':
				options = { transition: options };
				break;

			case 'undefined':
				options = {};
				break;

			case 'object':
				break;

			default:
				throw TypeError('options must be an object if defined, got ' + options);
		}

		switch (typeof options.transition) {
			case 'string':
				if (!(options.transition in transitions) && (options.transition !== 'instant')) {
					throw TypeError(options.transition + ' is not a valid transition');
				}
				break;

			case 'undefined':
				break;

			default:
				throw TypeError('transition must be a string if defined, got ' + options.transition);
		}

		switch (typeof options.duration) {
			case 'number':
				if (options.duration < 0) {
					throw TypeError('duration must be a non-negative integer, got ' + options.duration);
				}
				break;

			case 'undefined':
				break;

			default:
				throw TypeError('duration must be a number if defined, got ' + options.duration);
		}

		switch (typeof options.easing) {
			case 'string':
				if ( !(options.easing in easings) ) {
					throw TypeError(options.easing + ' is not a valid easing');
				}
				break;

			case 'undefined':
				break;

			default:
				throw TypeError('easing must be a string if defined, got ' + options.easing);
		}

		return options;
	}

	function validateCallback (callback) {
		switch (typeof callback) {
			case 'undefined':
				callback = function () {};
				break;

			case 'function':
				break;

			default:
				throw TypeError('callback must be a function if defined, got ' + callback);
		}

		return callback;
	}

	function swapper (elem1, elem2, options, callback) {
		validateElement(elem1);
		validateElement(elem2);

		if (typeof options === 'function') {
			callback = options;
			options  = {};
		}

		options  = validateOptions(options);
		callback = validateCallback(callback);

		if (elem1._swapper) {
			throw Error('elem1 is currently being swapped');
		}

		if (elem2._swapper) {
			throw Error('elem2 is currently being swapped');
		}

		if ( !isInDOM(elem1, true) ) {
			throw Error('elem1 must be in the DOM to be swapped');
		}

		elem1._swapper = true;
		elem2._swapper = true;

		removeNode(elem2);

		if (options.transition === 'instant') {
			insertAfter(elem2, elem1);
			removeNode(elem1);
			elem1._swapper = false;
			elem2._swapper = false;
			setTimeout(function () {
				callback();
			}, 0);
			return;
		}

		var transition = transitions[options.transition || 'fade'],
			easing     = easings[options.easing || 'ease-in-out'],
			duration   = options.duration || 300;

		insertAfter(elem2, elem1);

		var bounds          = elem1.getBoundingClientRect(),
			computedStyles1 = getStyles(elem1),
			computedStyles2 = getStyles(elem2),
			styles1         = getStyles(elem1, true),
			styles2         = getStyles(elem2, true);

		if (computedStyles1.display !== 'none') {
			elem2.style.position = 'fixed';
			elem2.style.top      = bounds.top  + 'px';
			elem2.style.left     = bounds.left + 'px';
		}
		elem2.style.height   = computedStyles2.height || computedStyles1.height;
		elem2.style.width    = computedStyles2.width  || computedStyles1.width;

		if ( transition[2] ) {
			insertBefore(elem2, elem1);
		}

		setTransform(elem1, NO_TRANSFORM );
		setTransform(elem2, transition[0].transform || NO_TRANSFORM);

		if ( transition[0].fade ) {
			elem2.style.opacity = '0';
		}

		if ( transition[1].fade ) {
			elem1.style.opacity = '1';
		}

		setTimeout(function () {
			var cssTransition = 'transform '+(duration/1000)+'s '+easing+', opacity '+(duration/1000)+'s '+easing;
			setTransition(elem1, cssTransition);
			setTransition(elem2, cssTransition);

			setTimeout(function () {
				setTransform(elem1, transition[1].transform || NO_TRANSFORM);
				setTransform(elem2, NO_TRANSFORM );

				if ( transition[0].fade ) {
					elem2.style.opacity = '1';
				}

				if ( transition[1].fade ) {
					elem1.style.opacity = '0';
				}

				bindCleanup();
				setTimeout(cleanupElems, duration + (IS_ANDROID ? 300 : 0));
			}, 0);
		}, 0);

		var cleanUpLock = false;

		function bindCleanup () {
			elem2.addEventListener('webkitTransitionEnd' , cleanupElems , false);
			elem2.addEventListener('transitionend'       , cleanupElems , false);
			elem2.addEventListener('oTransitionEnd'      , cleanupElems , false);
			elem2.addEventListener('otransitionend'      , cleanupElems , false);
			elem2.addEventListener('MSTransitionEnd'     , cleanupElems , false);
			elem2.addEventListener('transitionend'       , cleanupElems , false);
		}

		function unbindCleanup () {
			elem2.removeEventListener('webkitTransitionEnd' , cleanupElems);
			elem2.removeEventListener('transitionend'       , cleanupElems);
			elem2.removeEventListener('oTransitionEnd'      , cleanupElems);
			elem2.removeEventListener('otransitionend'      , cleanupElems);
			elem2.removeEventListener('MSTransitionEnd'     , cleanupElems);
			elem2.removeEventListener('transitionend'       , cleanupElems);
		}

		function cleanupElems () {
			if (cleanUpLock) {
				return;
			}
			cleanUpLock = true;

			unbindCleanup();

			removeNode(elem1);

			setTransition(elem1, '');
			setTransition(elem2, '');

			setTimeout(function () {
				setTransform(elem1, '');
				setTransform(elem2, '');

				if ( transition[0].fade ) {
					elem2.style.opacity = styles2.opacity;
				}

				if ( transition[1].fade ) {
					elem1.style.opacity = styles1.opacity;
				}

				elem2.style.position = styles2.position;
				elem2.style.top      = styles2.top;
				elem2.style.left     = styles2.left;
				elem2.style.height   = styles2.height;
				elem2.style.width    = styles2.width;

				elem1._swapper = false;
				elem2._swapper = false;

				callback();
			}, 0);
		}
	}

	if (Zepto) {
		Zepto.extend(Zepto.fn, {
			swapper : function (elem2, options, callback) {
				elem2 = Zepto(elem2)[0];

				this.forEach(function (elem1) {
					swapper(elem1, elem2, options, callback);
				});

				return this;
			}
		});
	}

	if (jQuery) {
		jQuery.fn.swapper = function (elem2, options, callback) {
			elem2 = jQuery(elem2)[0];

			this.each(function () {
				swapper(this, elem2, options, callback);
			});

			return this;
		};
	}

	return swapper;
}(window, document, window.Zepto, window.jQuery);
<|endoftext|>


<commit_before>/*global angular*/

(function() {
    'use strict';

    angular.module('willsp.pwSortable',[])

    .directive('pwSortable', function($document) {
        return {
            scope: {
                ngRepeat: '@',
                pwSortable: '@'
            },
            controller: function($scope, $element) {
                var direction = $scope.pwSortable;

                // Not ngRepeat
                var me = this;
                var horizontal = this.horizontal = direction === 'horizontal';
                this.plane = {};
                this.element = $element;

                this.mousemove = function mousemove(e) {
                    $scope.$apply(function() {
                        var plane = me.plane;
                        var orient = plane.orientation;
                        var parent = $element.parent();
                        var siblings = parent.children();
                        var next = $element.next();
                        var previous, offset, preprevious;

                        plane[orient] = e['page' + orient] - plane['start' + orient];
                        $element.css(plane.cssProp, plane[orient] + 'px');

                        // Get the previous sibling
                        for (var i = 0, max = siblings.length; i < max; i++) {
                            if (siblings[i] !== $element[0]) {
                                preprevious = previous;
                                previous = angular.element(siblings[i]);
                            } else {
                                break;
                            }
                        }

                        // Check top current vs offsetTop of neighbors
                        if (next.length && $element[0][plane.offset] > next[0][plane.offset]) {
                            next.after($element);

                            // correct for moving elements...
                            offset = next[0][plane.dimension] +
                                parseInt(window.getComputedStyle(next[0])[plane.margin1], 10) +
                                parseInt(window.getComputedStyle(next[0])[plane.margin2], 10);
                            plane[orient] = plane[orient] - offset;
                            plane['start' + orient] = plane['start' + orient] + offset;
                            $element.css(plane.cssProp, plane[orient] + 'px');

                        } else if (previous && $element[0][plane.offset] < previous[0][plane.offset]) {
                            if (preprevious) {
                                preprevious.after($element);
                            } else {
                                parent.prepend($element);
                            }

                            // correct for moving elements...
                            offset = previous[0][plane.dimension] +
                                parseInt(window.getComputedStyle(previous[0])[plane.margin1], 10) +
                                parseInt(window.getComputedStyle(previous[0])[plane.margin2], 10);
                            plane[orient] = plane[orient] + offset;
                            plane['start' + orient] = plane['start' + orient] - offset;
                            $element.css(plane.cssProp, plane[orient] + 'px');
                        }
                    });
                };

                this.mouseup = function mouseup(e) {
                    $scope.$apply(function() {
                        // Get the vars from the repeat
                        var expression = $scope.ngRepeat;
                        var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*$/);
                        var repeatScope = $scope.$parent;

                        var lhs = match[1];
                        var rhs = match[2];

                        var rmatch = rhs.match(/^([^\.\[]+)(.*)/);
                        /*jshint evil:true*/
                        var cont = eval("repeatScope[rmatch[1]]" + rmatch[2]);
                        /*jshint evil:false*/
                        var ref = repeatScope[lhs];
                        var ph = me.placeholder;

                        var family = $element.parent().children();
                        var phPos = [].indexOf.call(family, ph[0]);
                        var elPos = [].indexOf.call(family, $element[0]);

                        cont.splice(cont.indexOf(ref), 1);
                        cont.splice(elPos, 0, ref);
                        $element.css('position', '');
                        $element.css(me.plane.cssProp, '');

                        ph.after($element);
                        ph.remove();

                        $document.unbind('mousemove', me.mousemove);
                        $document.unbind('mouseup', me.mouseup);
                    });
                };
            }
        };
    })

    .directive('pwHandle', function($document) {
        return {
            require: '^pwSortable',
            link: function(scope, element, attr, sortCtrl) {

                element.on('mousedown', function(e) {
                    scope.$apply(function() {
                        e.stopPropagation();
                        e.preventDefault();

                        var plane;
                        var horizontal = sortCtrl.horizontal;
                        var sortable = sortCtrl.element;
                        var ph = sortCtrl.placeholder = angular.element(document.createComment('pwSortable placeholder'));
                        sortable.after(ph);

                        sortable.css({
                            position: 'relative'
                        });

                        sortCtrl.plane = {
                            X: 0,
                            Y: 0,
                            startX: 0,
                            startY: 0,
                            orientation: (horizontal) ? 'X' : 'Y',
                            cssProp: (horizontal) ? 'left' : 'top',
                            offset: (horizontal) ? 'offsetLeft' : 'offsetTop',
                            dimension: (horizontal) ? 'offsetWidth' : 'offsetHeight',
                            margin1: (horizontal) ? 'marginLeft' : 'marginTop',
                            margin2: (horizontal) ? 'marginRight' : 'marginBottom'
                        };

                        plane = sortCtrl.plane;
                        plane.startX = e.pageX - plane.X;
                        plane.startY = e.pageY - plane.Y;

                        $document.on('mousemove', sortCtrl.mousemove);
                        $document.on('mouseup', sortCtrl.mouseup);
                    });
                });
            }
        };
    });
}());
<commit_msg>Move back up to the parent(ngRepeat) scope, instead of creating an isolated scope.<commit_after>/*global angular*/

(function() {
    'use strict';

    angular.module('willsp.pwSortable',[])

    .directive('pwSortable', function($document) {
        return {
            controller: function($scope, $element, $attrs) {
                var direction = $attrs.pwSortable;

                // Not ngRepeat
                var me = this;
                var horizontal = this.horizontal = direction === 'horizontal';
                this.plane = {};
                this.element = $element;

                this.mousemove = function mousemove(e) {
                    $scope.$apply(function() {
                        var plane = me.plane;
                        var orient = plane.orientation;
                        var parent = $element.parent();
                        var siblings = parent.children();
                        var next = $element.next();
                        var previous, offset, preprevious;

                        plane[orient] = e['page' + orient] - plane['start' + orient];
                        $element.css(plane.cssProp, plane[orient] + 'px');

                        // Get the previous sibling
                        for (var i = 0, max = siblings.length; i < max; i++) {
                            if (siblings[i] !== $element[0]) {
                                preprevious = previous;
                                previous = angular.element(siblings[i]);
                            } else {
                                break;
                            }
                        }

                        // Check top current vs offsetTop of neighbors
                        if (next.length && $element[0][plane.offset] > next[0][plane.offset]) {
                            next.after($element);

                            // correct for moving elements...
                            offset = next[0][plane.dimension] +
                                parseInt(window.getComputedStyle(next[0])[plane.margin1], 10) +
                                parseInt(window.getComputedStyle(next[0])[plane.margin2], 10);
                            plane[orient] = plane[orient] - offset;
                            plane['start' + orient] = plane['start' + orient] + offset;
                            $element.css(plane.cssProp, plane[orient] + 'px');

                        } else if (previous && $element[0][plane.offset] < previous[0][plane.offset]) {
                            if (preprevious) {
                                preprevious.after($element);
                            } else {
                                parent.prepend($element);
                            }

                            // correct for moving elements...
                            offset = previous[0][plane.dimension] +
                                parseInt(window.getComputedStyle(previous[0])[plane.margin1], 10) +
                                parseInt(window.getComputedStyle(previous[0])[plane.margin2], 10);
                            plane[orient] = plane[orient] + offset;
                            plane['start' + orient] = plane['start' + orient] - offset;
                            $element.css(plane.cssProp, plane[orient] + 'px');
                        }
                    });
                };

                this.mouseup = function mouseup(e) {
                    $scope.$apply(function() {
                        // Get the vars from the repeat
                        var expression = $attrs.ngRepeat;
                        var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*$/);

                        var lhs = match[1];
                        var rhs = match[2];

                        var rmatch = rhs.match(/^([^\.\[]+)(.*)/);
                        /*jshint evil:true*/
                        var cont = eval("$scope[rmatch[1]]" + rmatch[2]);
                        /*jshint evil:false*/
                        var ref = $scope[lhs];
                        var ph = me.placeholder;

                        var family = $element.parent().children();
                        var phPos = [].indexOf.call(family, ph[0]);
                        var elPos = [].indexOf.call(family, $element[0]);

                        cont.splice(cont.indexOf(ref), 1);
                        cont.splice(elPos, 0, ref);
                        $element.css('position', '');
                        $element.css(me.plane.cssProp, '');

                        ph.after($element);
                        ph.remove();

                        $document.unbind('mousemove', me.mousemove);
                        $document.unbind('mouseup', me.mouseup);
                    });
                };
            }
        };
    })

    .directive('pwHandle', function($document) {
        return {
            require: '^pwSortable',
            link: function(scope, element, attr, sortCtrl) {

                element.on('mousedown', function(e) {
                    scope.$apply(function() {
                        e.stopPropagation();
                        e.preventDefault();

                        var plane;
                        var horizontal = sortCtrl.horizontal;
                        var sortable = sortCtrl.element;
                        var ph = sortCtrl.placeholder = angular.element(document.createComment('pwSortable placeholder'));
                        sortable.after(ph);

                        sortable.css({
                            position: 'relative'
                        });

                        sortCtrl.plane = {
                            X: 0,
                            Y: 0,
                            startX: 0,
                            startY: 0,
                            orientation: (horizontal) ? 'X' : 'Y',
                            cssProp: (horizontal) ? 'left' : 'top',
                            offset: (horizontal) ? 'offsetLeft' : 'offsetTop',
                            dimension: (horizontal) ? 'offsetWidth' : 'offsetHeight',
                            margin1: (horizontal) ? 'marginLeft' : 'marginTop',
                            margin2: (horizontal) ? 'marginRight' : 'marginBottom'
                        };

                        plane = sortCtrl.plane;
                        plane.startX = e.pageX - plane.X;
                        plane.startY = e.pageY - plane.Y;

                        $document.on('mousemove', sortCtrl.mousemove);
                        $document.on('mouseup', sortCtrl.mouseup);
                    });
                });
            }
        };
    });
}());
<|endoftext|>


<commit_before> /*!
 * Copyright Ben Olson (https://github.com/bseth99/jquery-ui-extensions)
 * jQuery UI ComboBox @VERSION
 *
 *  Adapted from Jörn Zaefferer original implementation at
 *  http://www.learningjquery.com/2010/06/a-jquery-ui-combobox-under-the-hood
 *
 *  And the demo at
 *  http://jqueryui.com/autocomplete/#combobox
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 */

(function( $, undefined ) {

   $.widget( "ui.combobox", {

      version: "@VERSION",

      widgetEventPrefix: "combobox",

      uiCombo: null,
      uiInput: null,
      _wasOpen: false,

      _create: function() {

         var self = this,
             select = this.element.hide(),
             input, wrapper;

         input = this.uiInput =
                  $( "<input />" )
                      .insertAfter(select)
                      .addClass("ui-widget ui-widget-content ui-corner-left ui-combobox-input")
                      .val( select.children(':selected').text() );

         wrapper = this.uiCombo =
            input.wrap( '' )
               .parent()
               .addClass( 'ui-combobox' )
               .insertAfter( select );

         input
          .autocomplete({

             delay: 0,
             minLength: 0,

             appendTo: wrapper,
             source: $.proxy( this, "_linkSelectList" )

          });

         $( "<button>" )
            .attr( "tabIndex", -1 )
            .attr( "type", "button" )
            .insertAfter( input )
            .button({
               icons: {
                  primary: "ui-icon-triangle-1-s"
               },
               text: false
            })
            .removeClass( "ui-corner-all" )
            .addClass( "ui-corner-right ui-button-icon ui-combobox-button" );

         // Our items have HTML tags.  The default rendering uses text()
         // to set the content of the  tag.  We need html().
         input.data( "ui-autocomplete" )._renderItem = function( ul, item ) {

               return $( "
" )
                           .append( $( "" ).html( item.label ) )
                           .appendTo( ul );

            };

         this._on( this._events );

      },

      _linkSelectList: function( request, response ) {

         var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), 'i' );
         response( this.element.children('option').map(function() {

                  var text = $( this ).text();

                  if ( this.value && ( !request.term || matcher.test(text) ) ) {

                     return {
                           label: text.replace(
                              new RegExp(
                                  "(?![^&;]+;)(?!<[^<>]*)(" +
                                  $.ui.autocomplete.escapeRegex(request.term) +
                                  ")(?![^<>]*>)(?![^&;]+;)", "gi"),
                                  "$1"),
                           value: text,
                           option: this
                        };
                  }
              })
           );
      },

      _events: {

         "autocompletechange input" : function(event, ui) {

            var $el = $(event.currentTarget);

            if ( !ui.item ) {

               var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $el.val() ) + "$", "i" ),
               valid = false;

               this.element.children( "option" ).each(function() {
                     if ( $( this ).text().match( matcher ) ) {
                        this.selected = valid = true;
                        return false;
                     }
                  });

                if ( !valid ) {

                   // remove invalid value, as it didn't match anything
                   $el.val( "" );
                   this.element.prop('selectedIndex', -1);
                   //return false;

                }
            }

            this._trigger( "change", event, {
                  item: ui.item ? ui.item.option : null
                });

         },

         "autocompleteselect input": function( event, ui ) {

            ui.item.option.selected = true;
            this._trigger( "select", event, {
                  item: ui.item.option
               });

         },

         "autocompleteopen input": function ( event, ui ) {

            this.uiCombo.children('.ui-autocomplete')
               .outerWidth(this.uiCombo.outerWidth(true));
         },

         "mousedown .ui-combobox-button" : function ( event ) {
            this._wasOpen = this.uiInput.autocomplete("widget").is(":visible");
         },

         "click .ui-combobox-button" : function( event ) {

            this.uiInput.focus();

            // close if already visible
            if (this._wasOpen)
               return;

            // pass empty string as value to search for, displaying all results
            this.uiInput.autocomplete("search", "");

         }

      },

      value: function ( newVal ) {
         var select = this.element,
             valid = false,
             selected;

         if ( !arguments.length ) {
            selected = select.children( ":selected" );
            return selected.length > 0 ? selected.val() : null;
         }

         select.prop('selectedIndex', -1);
         select.children('option').each(function() {
               if ( this.value == newVal ) {
                  this.selected = valid = true;
                  return false;
               }
            });

         if ( valid ) {
            this.uiInput.val(select.children(':selected').text());
         } else {
            this.uiInput.val( "" );
            this.element.prop('selectedIndex', -1);
         }

      },

      _destroy: function () {
         this.element.show();
         this.uiCombo.replaceWith( this.element );
      },

      widget: function () {
         return this.uiCombo;
      },

      _getCreateEventData: function() {

         return {
            select: this.element,
            combo: this.uiCombo,
            input: this.uiInput
         };
      }

    });

}(jQuery));
<commit_msg>Force autocomplete to reset internal state when invalid value is entered<commit_after> /*!
 * Copyright Ben Olson (https://github.com/bseth99/jquery-ui-extensions)
 * jQuery UI ComboBox @VERSION
 *
 *  Adapted from Jörn Zaefferer original implementation at
 *  http://www.learningjquery.com/2010/06/a-jquery-ui-combobox-under-the-hood
 *
 *  And the demo at
 *  http://jqueryui.com/autocomplete/#combobox
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 */

(function( $, undefined ) {

   $.widget( "ui.combobox", {

      version: "@VERSION",

      widgetEventPrefix: "combobox",

      uiCombo: null,
      uiInput: null,
      _wasOpen: false,

      _create: function() {

         var self = this,
             select = this.element.hide(),
             input, wrapper;

         input = this.uiInput =
                  $( "<input />" )
                      .insertAfter(select)
                      .addClass("ui-widget ui-widget-content ui-corner-left ui-combobox-input")
                      .val( select.children(':selected').text() );

         wrapper = this.uiCombo =
            input.wrap( '' )
               .parent()
               .addClass( 'ui-combobox' )
               .insertAfter( select );

         input
          .autocomplete({

             delay: 0,
             minLength: 0,

             appendTo: wrapper,
             source: $.proxy( this, "_linkSelectList" )

          });

         $( "<button>" )
            .attr( "tabIndex", -1 )
            .attr( "type", "button" )
            .insertAfter( input )
            .button({
               icons: {
                  primary: "ui-icon-triangle-1-s"
               },
               text: false
            })
            .removeClass( "ui-corner-all" )
            .addClass( "ui-corner-right ui-button-icon ui-combobox-button" );

         // Our items have HTML tags.  The default rendering uses text()
         // to set the content of the  tag.  We need html().
         input.data( "ui-autocomplete" )._renderItem = function( ul, item ) {

               return $( "
" )
                           .append( $( "" ).html( item.label ) )
                           .appendTo( ul );

            };

         this._on( this._events );

      },

      _linkSelectList: function( request, response ) {

         var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), 'i' );
         response( this.element.children('option').map(function() {

                  var text = $( this ).text();

                  if ( this.value && ( !request.term || matcher.test(text) ) ) {

                     return {
                           label: text.replace(
                              new RegExp(
                                  "(?![^&;]+;)(?!<[^<>]*)(" +
                                  $.ui.autocomplete.escapeRegex(request.term) +
                                  ")(?![^<>]*>)(?![^&;]+;)", "gi"),
                                  "$1"),
                           value: text,
                           option: this
                        };
                  }
              })
           );
      },

      _events: {

         "autocompletechange input" : function(event, ui) {

            var $el = $(event.currentTarget);

            if ( !ui.item ) {

               var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $el.val() ) + "$", "i" ),
               valid = false;

               this.element.children( "option" ).each(function() {
                     if ( $( this ).text().match( matcher ) ) {
                        this.selected = valid = true;
                        return false;
                     }
                  });

                if ( !valid ) {

                   // remove invalid value, as it didn't match anything
                   $el.val( '' );

                   // Internally, term must change before another search is performed
                   // if the same search is performed again, the menu won't be shown
                   // because the value didn't actually change via a keyboard event
                   $el.data( 'ui-autocomplete' ).term = '';

                   this.element.prop('selectedIndex', -1);

                }
            }

            this._trigger( "change", event, {
                  item: ui.item ? ui.item.option : null
                });

         },

         "autocompleteselect input": function( event, ui ) {

            ui.item.option.selected = true;
            this._trigger( "select", event, {
                  item: ui.item.option
               });

         },

         "autocompleteopen input": function ( event, ui ) {

            this.uiCombo.children('.ui-autocomplete')
               .outerWidth(this.uiCombo.outerWidth(true));
         },

         "mousedown .ui-combobox-button" : function ( event ) {
            this._wasOpen = this.uiInput.autocomplete("widget").is(":visible");
         },

         "click .ui-combobox-button" : function( event ) {

            this.uiInput.focus();

            // close if already visible
            if (this._wasOpen)
               return;

            // pass empty string as value to search for, displaying all results
            this.uiInput.autocomplete("search", "");

         }

      },

      value: function ( newVal ) {
         var select = this.element,
             valid = false,
             selected;

         if ( !arguments.length ) {
            selected = select.children( ":selected" );
            return selected.length > 0 ? selected.val() : null;
         }

         select.prop('selectedIndex', -1);
         select.children('option').each(function() {
               if ( this.value == newVal ) {
                  this.selected = valid = true;
                  return false;
               }
            });

         if ( valid ) {
            this.uiInput.val(select.children(':selected').text());
         } else {
            this.uiInput.val( "" );
            this.element.prop('selectedIndex', -1);
         }

      },

      _destroy: function () {
         this.element.show();
         this.uiCombo.replaceWith( this.element );
      },

      widget: function () {
         return this.uiCombo;
      },

      _getCreateEventData: function() {

         return {
            select: this.element,
            combo: this.uiCombo,
            input: this.uiInput
         };
      }

    });

}(jQuery));
<|endoftext|>