<commit_before>var m = require("moment");

/*
 * Function to check db id.
 */
exports.isHex = function( wid ){

	var str = wid.split("");
	for(i in str){

		if(str[i] > "f")
			return false;
	}
	return true;

}

/*
 * Function to check if a user id has access to a document. By now, a user has acces to a document if
 * has the ownership of the document or belongs to the rcpts list of the document.
 */
exports.check_access = function( params, doc ){

	return doc.uid == params.uid || (doc.rcpts != undefined && doc.rcpts.indexOf(params.uid) >= 0);
}

/*
 * gets inner field of the object
 */
var get_field = exports.get_field =  function( obj, fname ){

	if( obj == undefined )
		return undefined;

	var idx = fname.indexOf(".");
	if(  idx != -1 ){

		obj = obj[fname.substr(0,idx)];
		fname = fname.substr(idx+1,fname.length-1);
		return get_field(obj,fname);
	}else
		return obj[fname];

}

/*
 * sets the inner field of the object to the value.
 */
var set_field = exports.set_field = function(obj, fname, value ){

	var idx = fname.indexOf(".");

	if(  idx != -1 ){

		var cfield = fname.substr(0,idx);
		if( obj[cfield] == undefined )
			obj[cfield] = {};
		obj = obj[cfield];
		fname = fname.substr(idx+1,fname.length-1);

		set_field(obj,fname,value);
	}else
		obj[fname] = value;

}

/*
 * deletes inner field of the object.
 */
var del_field = exports.del_field = function(obj, fname ){

	if( obj == undefined )
		return;

	var idx = fname.indexOf(".");
	if(  idx != -1 ){

		var cfield = fname.substr(0,idx);
		if( obj[cfield] == undefined )
			obj[cfield] = {};
		obj = obj[cfield];
		fname = fname.substr(idx+1,fname.length-1);

		del_field(obj,fname);
	}else
		delete obj[fname];

}

/*
 * List remote procedures
 */
exports.list_remote_procedures = function( api ){

	var list = " ";
	for(key in api.remote){

		list += key + " ";
	}
	return list;
}

/*
 * Change default behaviour of console.log to print timestamp before any message
 * TODO: si se llama mas de una vez los timestamp de van superponiendo a la izquierda del mensaje.
 */
var f = console.log;
exports.change_console_log_printing_format = function(){

	console.log = function(){

		var args = Array.prototype.slice.call(arguments);
		args[0] = "[%s] " + args[0];
		args.splice(1,0,m().format("DD/MM/YYYY H:mm:ss"));
		f.apply(this, args);

	}

}

<commit_msg>added function start_expire_timer<commit_after>var m = require("moment");
var db = require("./db");

/*
 * Function to check db id.
 */
exports.isHex = function( wid ){

	var str = wid.split("");
	for(i in str){

		if(str[i] > "f")
			return false;
	}
	return true;

}

/*
 * Function to check if a user id has access to a document. By now, a user has acces to a document if
 * has the ownership of the document or belongs to the rcpts list of the document.
 */
exports.check_access = function( params, doc ){

	return doc.uid == params.uid || (doc.rcpts != undefined && doc.rcpts.indexOf(params.uid) >= 0);
}

/*
 * gets inner field of the object
 */
var get_field = exports.get_field =  function( obj, fname ){

	if( obj == undefined )
		return undefined;

	var idx = fname.indexOf(".");
	if(  idx != -1 ){

		obj = obj[fname.substr(0,idx)];
		fname = fname.substr(idx+1,fname.length-1);
		return get_field(obj,fname);
	}else
		return obj[fname];

}

/*
 * sets the inner field of the object to the value.
 */
var set_field = exports.set_field = function(obj, fname, value ){

	var idx = fname.indexOf(".");

	if(  idx != -1 ){

		var cfield = fname.substr(0,idx);
		if( obj[cfield] == undefined )
			obj[cfield] = {};
		obj = obj[cfield];
		fname = fname.substr(idx+1,fname.length-1);

		set_field(obj,fname,value);
	}else
		obj[fname] = value;

}

/*
 * deletes inner field of the object.
 */
var del_field = exports.del_field = function(obj, fname ){

	if( obj == undefined )
		return;

	var idx = fname.indexOf(".");
	if(  idx != -1 ){

		var cfield = fname.substr(0,idx);
		if( obj[cfield] == undefined )
			obj[cfield] = {};
		obj = obj[cfield];
		fname = fname.substr(idx+1,fname.length-1);

		del_field(obj,fname);
	}else
		delete obj[fname];

}

/*
 * List remote procedures
 */
exports.list_remote_procedures = function( api ){

	var list = " ";
	for(key in api.remote){

		list += key + " ";
	}
	return list;
}

/*
 * Change default behaviour of console.log to print timestamp before any message
 * TODO: si se llama mas de una vez los timestamp de van superponiendo a la izquierda del mensaje.
 */
var f = console.log;
exports.change_console_log_printing_format = function(){

	console.log = function(){

		var args = Array.prototype.slice.call(arguments);
		args[0] = "[%s] " + args[0];
		args.splice(1,0,m().format("DD/MM/YYYY H:mm:ss"));
		f.apply(this, args);

	}

}

/*
 * Launch a timer passing the handler to remove doc and its related events when it expires.
 */
exports.start_expire_timer = function( catalog, doc, ret_handler ){

	var interval = doc.etime - new Date().getTime();

	if(interval > 0)
		setTimeout( function(){

				db.remove_expired(catalog, doc.wid, function(err,n){

					if(!err)
						if(ret_handler)
							ret_handler(n);
					else
						throw err;
				});
		}, interval );

}

<|endoftext|>


<commit_before>'use strict';

const queryBaseURL = 'http://classes.berkeley.edu/enrollment/update/';

function getClassStatus(termID, classID, callback) {
    const queryURL = queryBaseURL + termID + '/' + classID;
    $.getJSON('https://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent('select * from json where url="' + queryURL + '"') + '&format=json').done(function(data) {
        callback(data['query']['results']['json']);
    }).fail(function() {
        callback(null);
    });
}

$(document).ready(function() {
    $.getJSON('ajax/terms.json').done(function(terms) {
        $.each(terms, function(termName, termID) {
            $('#termID').append($('<option>', {value : termID}).text(termName));
        });
    }).fail(function() {
        window.alert('Terms are not loaded!');
        window.close();
    });
    $('#classID').bind('keypress', function(event) {
        if (event.keyCode == '13') {
            $('#selectBtn').click();
        }
    });
    $('#selectBtn').click(function() {
        const classID = $('#classID').val();
        if (/^\d+$/.test(classID) && classID.length == 5) {
            getClassStatus($('#termID').val(), classID, function(data) {
                if (data == null) {
                    window.alert('Unknown network error!');
                } else if (data['classSections'] == null) {
                    window.alert('You entered an invalid Class ID!');
                    $('#classID').val('');
                    $('#classID').focus();
                } else {
                    window.alert(JSON.stringify(data));
                }
            });
        } else {
            window.alert('Please enter a five-digit integer in Class ID!');
            $('#classID').val('');
            $('#classID').focus();
        }
    });
});
<commit_msg>disable button when querying<commit_after>'use strict';

const queryBaseURL = 'http://classes.berkeley.edu/enrollment/update/';

function getClassStatus(termID, classID, callback) {
    const queryURL = queryBaseURL + termID + '/' + classID;
    $.getJSON('https://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent('select * from json where url="' + queryURL + '"') + '&format=json').done(function(data) {
        callback(data['query']['results']['json']);
    }).fail(function() {
        callback(null);
    });
}

$(document).ready(function() {
    $.getJSON('ajax/terms.json').done(function(terms) {
        $.each(terms, function(termName, termID) {
            $('#termID').append($('<option>', {value : termID}).text(termName));
        });
    }).fail(function() {
        window.alert('Terms are not loaded!');
        window.close();
    });
    $('#classID').bind('keypress', function(event) {
        if (event.keyCode == '13') {
            $('#selectBtn').click();
        }
    });
    $('#selectBtn').click(function() {
        const classID = $('#classID').val();
        if (/^\d+$/.test(classID) && classID.length == 5) {
            $('#selectBtn').prop('disabled', true);
            getClassStatus($('#termID').val(), classID, function(data) {
                if (data == null) {
                    window.alert('Unknown network error!');
                } else if (data['classSections'] == null) {
                    window.alert('You entered an invalid Class ID!');
                    $('#classID').val('');
                    $('#classID').focus();
                } else {
                    window.alert(JSON.stringify(data));
                }
                $('#selectBtn').prop('disabled', false);
            });
        } else {
            window.alert('Please enter a five-digit integer in Class ID!');
            $('#classID').val('');
            $('#classID').focus();
        }
    });
});
<|endoftext|>


<commit_before>var fixed = false;
$(document).scroll(function() {
    if( $(this).scrollTop() >= 650 ) {
        if( !fixed ) {
            fixed = true;
            $('li a').css({color:'black'});
        }
    } else {
        if( fixed ) {
            fixed = false;
            $('li a').css({color:'white'});
        }
    }
});

$(function() {
  $('a[href*="#"]:not([href="#"])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html, body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });
});

$(window).scroll(function(){
    $(".title").css("opacity", 1 - $(window).scrollTop() / 250);
  });
$(window).scroll(function(){
    $(".subtitle").css("opacity", 1 - $(window).scrollTop() / 350);
  });

$(window).scroll(function(){
    $(".logo").css("opacity", 1 - $(window).scrollTop() / 3000);
  });<commit_msg>Delete index.js<commit_after><|endoftext|>


<commit_before>var alexa = require("alexa-app");
var fs = require('fs');
var request = require('request');

var app = new alexa.app("youtube");

var herokuAppUrl = process.env.HEROKU_APP_URL;
if (!herokuAppUrl || herokuAppUrl === 0) {
  herokuAppUrl = 'https://dmhacker-youtube.herokuapp.com';
}

var lastSearch;
var lastToken;

var lastPlaybackStart;
var lastPlaybackStop;

app.pre = function(req, response, type) {
    if (req.data.session !== undefined) {
        if (req.data.session.application.applicationId !== process.env.ALEXA_APPLICATION_ID) {
            response.fail("Invalid application");
        }
    }
    else {
        if (req.applicationId !== process.env.ALEXA_APPLICATION_ID) {
            response.fail("Invalid application");
        }
    }
};

app.intent("GetVideoIntent", {
        "slots": {
            "VideoQuery": "VIDEOS",
        },
        "utterances": [
            "search for {-|VideoQuery}",
            "find {-|VideoQuery}",
            "play {-|VideoQuery}",
            "start playing {-|VideoQuery}",
            "put on {-|VideoQuery}"
        ]
    },
    function(req, response) {
        return get_executable_promise(req, response, 'english');
    }
);

app.intent("GetVideoGermanIntent", {
        "slots": {
            "VideoQuery": "VIDEOS",
        },
        "utterances": [
            "suchen nach {-|VideoQuery}",
            "finde {-|VideoQuery}",
            "spielen {-|VideoQuery}",
            "anfangen zu spielen {-|VideoQuery}",
            "anziehen {-|VideoQuery}"
        ]
    },
    function(req, response) {
        return get_executable_promise(req, response, 'german');
    }
);

function get_executable_promise(req, response, language) {
    var query = req.slot("VideoQuery");

    console.log('Searching ... ' + query);

    return new Promise((resolve, reject) => {

      request(herokuAppUrl + '/alexa-search/' + new Buffer(query).toString('base64'), function(err, res, body) {
          if (err) {
              reject(err.message);
          } else {
            var bodyJSON = JSON.parse(body);
            if (bodyJSON.status === 'error' && bodyJSON.message === 'No results found') {
                resolve({
                    message: language === 'german' ? 'Keine Ergebnisse auf Youtube gefunden.' : query + ' did not return any results on YouTube.',
                    url: null,
                    metadata: null
                });
            }
            else {
                lastSearch = herokuAppUrl + bodyJSON.link;
                console.log('Stored @ '+lastSearch);
                var metadata = bodyJSON.info;
                lastToken = metadata.id;
                resolve({
                    message: language === 'german' ? 'Ich spiele jetzt ' + metadata.title + '.' : 'I am now playing ' + metadata.title + '.',
                    url: lastSearch,
                    metadata: metadata
                });
            }
          }
      });
    }).then(function (content) {
        var message = content.message;
        var streamUrl = content.url;
        var metadata = content.metadata;
        response.say(message);
        if (streamUrl) {
            response.audioPlayerPlayStream('REPLACE_ALL', {
                'url': streamUrl,
                'streamFormat': 'AUDIO_MPEG',
                'token': metadata.id,
                'offsetInMilliseconds': 0
            });
            response.card({
                'type': 'Simple',
                'title': 'Search for "' + query + '"',
                'content': 'Alexa found "' + metadata.title + '" at ' + metadata.original + '.'
            });
        }
        response.send();
        lastPlaybackStart = new Date().getTime();
    }).catch(function(reason) {
        response.fail(reason);
    });
}

app.audioPlayer("PlaybackStarted", function(req, response) {
    console.log('Playback started.');
});

app.audioPlayer("PlaybackFailed", function(req, response) {
    console.log('Playback failed.');
    console.log(req.data.request);
    console.log(req.data.request.error);
});

app.intent("AMAZON.PauseIntent", {}, function(req, response) {
    response.audioPlayerStop();
    lastPlaybackStop = new Date().getTime();
    response.send();
});

app.intent("AMAZON.ResumeIntent", {}, function(req, response) {
    if (lastSearch === undefined) {
        response.say(req.data.request.locale === 'de-DE' ? 'Sie spielen derzeit nichts.' : 'You are not playing anything currently.');
    } else {
        response.audioPlayerPlayStream('REPLACE_ALL', {
            'url': lastSearch,
            'streamFormat': 'AUDIO_MPEG',
            'token': lastToken,
            'offsetInMilliseconds': lastPlaybackStop - lastPlaybackStart
        });
    }
    response.send();
});

app.intent("AMAZON.StopIntent", {}, function(req, response) {
    lastSearch = undefined;
    response.audioPlayerStop();
    response.audioPlayerClearQueue();
    response.send();
});

app.intent("AMAZON.RepeatIntent", {}, function(req, response) {
    if (lastSearch === undefined) {
        response.say(req.data.request.locale === 'de-DE' ? 'Sie haben vorher kein Video gespielt.' : 'You were not playing any video previously.');
    } else {
        response.audioPlayerPlayStream('REPLACE_ALL', {
            'url': lastSearch,
            'streamFormat': 'AUDIO_MPEG',
            'token': lastToken,
            'offsetInMilliseconds': 0
        });
    }
    response.send();
})

exports.handler = app.lambda();
<commit_msg>use de-DE as locale<commit_after>var alexa = require("alexa-app");
var fs = require('fs');
var request = require('request');

var app = new alexa.app("youtube");

var herokuAppUrl = process.env.HEROKU_APP_URL;
if (!herokuAppUrl || herokuAppUrl === 0) {
  herokuAppUrl = 'https://dmhacker-youtube.herokuapp.com';
}

var lastSearch;
var lastToken;

var lastPlaybackStart;
var lastPlaybackStop;

app.pre = function(req, response, type) {
    if (req.data.session !== undefined) {
        if (req.data.session.application.applicationId !== process.env.ALEXA_APPLICATION_ID) {
            response.fail("Invalid application");
        }
    }
    else {
        if (req.applicationId !== process.env.ALEXA_APPLICATION_ID) {
            response.fail("Invalid application");
        }
    }
};

app.intent("GetVideoIntent", {
        "slots": {
            "VideoQuery": "VIDEOS",
        },
        "utterances": [
            "search for {-|VideoQuery}",
            "find {-|VideoQuery}",
            "play {-|VideoQuery}",
            "start playing {-|VideoQuery}",
            "put on {-|VideoQuery}"
        ]
    },
    function(req, response) {
        return get_executable_promise(req, response, 'en-US');
    }
);

app.intent("GetVideoGermanIntent", {
        "slots": {
            "VideoQuery": "VIDEOS",
        },
        "utterances": [
            "suchen nach {-|VideoQuery}",
            "finde {-|VideoQuery}",
            "spielen {-|VideoQuery}",
            "anfangen zu spielen {-|VideoQuery}",
            "anziehen {-|VideoQuery}"
        ]
    },
    function(req, response) {
        return get_executable_promise(req, response, 'de-DE');
    }
);

function get_executable_promise(req, response, language) {
    var query = req.slot("VideoQuery");

    console.log('Searching ... ' + query);

    return new Promise((resolve, reject) => {

      request(herokuAppUrl + '/alexa-search/' + new Buffer(query).toString('base64'), function(err, res, body) {
          if (err) {
              reject(err.message);
          } else {
            var bodyJSON = JSON.parse(body);
            if (bodyJSON.status === 'error' && bodyJSON.message === 'No results found') {
                resolve({
                    message: language === 'de-DE' ? 'Keine Ergebnisse auf Youtube gefunden.' : query + ' did not return any results on YouTube.',
                    url: null,
                    metadata: null
                });
            }
            else {
                lastSearch = herokuAppUrl + bodyJSON.link;
                console.log('Stored @ '+lastSearch);
                var metadata = bodyJSON.info;
                lastToken = metadata.id;
                resolve({
                    message: language === 'de-DE' ? 'Ich spiele jetzt ' + metadata.title + '.' : 'I am now playing ' + metadata.title + '.',
                    url: lastSearch,
                    metadata: metadata
                });
            }
          }
      });
    }).then(function (content) {
        var message = content.message;
        var streamUrl = content.url;
        var metadata = content.metadata;
        response.say(message);
        if (streamUrl) {
            response.audioPlayerPlayStream('REPLACE_ALL', {
                'url': streamUrl,
                'streamFormat': 'AUDIO_MPEG',
                'token': metadata.id,
                'offsetInMilliseconds': 0
            });
            response.card({
                'type': 'Simple',
                'title': 'Search for "' + query + '"',
                'content': 'Alexa found "' + metadata.title + '" at ' + metadata.original + '.'
            });
        }
        response.send();
        lastPlaybackStart = new Date().getTime();
    }).catch(function(reason) {
        response.fail(reason);
    });
}

app.audioPlayer("PlaybackStarted", function(req, response) {
    console.log('Playback started.');
});

app.audioPlayer("PlaybackFailed", function(req, response) {
    console.log('Playback failed.');
    console.log(req.data.request);
    console.log(req.data.request.error);
});

app.intent("AMAZON.PauseIntent", {}, function(req, response) {
    response.audioPlayerStop();
    lastPlaybackStop = new Date().getTime();
    response.send();
});

app.intent("AMAZON.ResumeIntent", {}, function(req, response) {
    if (lastSearch === undefined) {
        response.say(req.data.request.locale === 'de-DE' ? 'Sie spielen derzeit nichts.' : 'You are not playing anything currently.');
    } else {
        response.audioPlayerPlayStream('REPLACE_ALL', {
            'url': lastSearch,
            'streamFormat': 'AUDIO_MPEG',
            'token': lastToken,
            'offsetInMilliseconds': lastPlaybackStop - lastPlaybackStart
        });
    }
    response.send();
});

app.intent("AMAZON.StopIntent", {}, function(req, response) {
    lastSearch = undefined;
    response.audioPlayerStop();
    response.audioPlayerClearQueue();
    response.send();
});

app.intent("AMAZON.RepeatIntent", {}, function(req, response) {
    if (lastSearch === undefined) {
        response.say(req.data.request.locale === 'de-DE' ? 'Sie haben vorher kein Video gespielt.' : 'You were not playing any video previously.');
    } else {
        response.audioPlayerPlayStream('REPLACE_ALL', {
            'url': lastSearch,
            'streamFormat': 'AUDIO_MPEG',
            'token': lastToken,
            'offsetInMilliseconds': 0
        });
    }
    response.send();
})

exports.handler = app.lambda();
<|endoftext|>


<commit_before>/*global document, window, setInterval */

/**
 * Juxta 0.0.1
 *
 * Copyright (c) 2010-2011 Alexey Golovnya
 * Licensed under the MIT license
 * http://juxta.ru
 */

/**
 * @class Juxta base application
 */
var Juxta = function() {

	var that = this;

	/**
	 * @type {String}
	 */
	this._state = null;

	/**
	 * @type Juxta.Cache
	 */
	this._cache = new Juxta.Cache();

	/**
	 * @type {Juxta.Connection}
	 */
	this._connection = new Juxta.Connection();

	/**
	 * @type {Juxta.Sidebar}
	 */
	this._sidebar = new Juxta.Sidebar(this._connection);

	/**
	 * Request/response
	 * @type Juxta.Request
	 */
	this._request = new Juxta.Request(this._connection, this._cache, {
		request: {
			beforeSend: function() {
				that.loading();
			},
			complete: function() {
				that.loading(false);
			},
			error: function(xhr, status) {
				if (status == 'parsererror') {
					that.error('Answer parsing error');
				} else {
					that.error(xhr.status + ' ' + xhr.statusText);
				}
			}
		},
		response: {
			connectionError: function(response) {
				that.error(response.error);
				that._auth.show();
			},
			sessionNotFound: function() {
				that.redirect('login');
			},
			error: function(response) {
				that.error(response.error);
			},
			unknowStatus: function() {
				that.error('Response with unknow status recived');
			}
		}
	});

	/**
	 * Notification messages
	 * @type {Juxta.Notification}
	 */
	this._notification = new Juxta.Notification();

	/**
	 * Server explorer
	 * @type {Juxta.Explorer}
	 */
	this._explorer = new Juxta.Explorer('#explorer', this._request);

	/**
	 * Table data browser
	 * @type {Juxta.Browser}
	 */
	this.browser = new Juxta.Browser('#data-browser', this._request);

	/**
	 * Table editor
	 * @type {Juxta.Table}
	 */
	this.table = new Juxta.Table('#table', this._request);

	/**
	 * Server inofrmation
	 * @type {Juxta.Server}
	 */
	this.server = new Juxta.Server('#server-info', this._request);

	/**
	 * Connect to server form
	 * @type {Juxta.Auth}
	 */
	this._auth = new Juxta.Auth('#login', this._request);

	/**
	 * Float box
	 * @type {Juxta.Modal}
	 */
	this.messageBox = new Juxta.Modal('#message');

	//
	$('.header-change-connection-link').on('click', function() {
		//
		var container = $('.header-connections-container'),
			list = container.find('.header-connections');

		container.css({right: ''}).toggle();

		if (container.is(':visible') && $('body').width() - container.offset().left < container.width()) {
			container.css({right: 7})
		}

		list.toggleClass('scroll', list.prop('scrollHeight') > list.prop('offsetHeight'));

		return false;
	});

	//
	this._connection.on('change', $.proxy(this._changeConnectionCallback, this));

	// Show Juxta when application ready to show
	$.each([this._explorer, this.server, this.browser, this.table], function(i, application) {
		application.on('ready', $.proxy(that.show, that));
	});

	//
	this._auth
		.on('before-show', $.proxy(function() {
			//
			this.hide()._updateWindowTitle();
			this._connection.reset();

		}, this))
		.on('login', function(connection) {
			that._connection.set(connection.cid, connection);
			that.redirect('databases', connection.cid);
		})
		.on('logout', function() {
			that._cache.flush();
			that._updateWindowTitle().redirect('login');
		})
		.on('change', function(cid) {
			that.redirect('', cid);
		});

	// Notifications
	this._auth.on('notify', function(message, type, options) {
		if (type === 'error') {
			that.error(message, options);
		} else if (type === 'loading') {
			that.loading(message, options);
		} else {
			that.notify(message, options);
		}
	});

	//
	$('#header a[name=about]').bind('click', function() {
		that.about();
		return false;
	});

	//
	$('#header .sql a').bind('click', function() {
		if (that.browser.is(':visible') && that.browser.mode == 'browse') {
			that.browser.toggleEditor();
			return false;
		}
	});

	$('#header a[name=logout]').click(function() {
		that._auth.logout();
		return false;
	});

	// @todo Remove this from here
	$('.float-box').draggable({scroll: false, handle: 'h3'});

	// @todo Remove this from here
	$(document.body).bind('click', function() {
		$('.context:visible').trigger('hide').hide();
	});

	this.run();

};

/**
 * Default MySQL port
 * @type {Number}
 */
Juxta.defaultPort = 3306;

/**
 * Run application
 * @return {Juxta}
 */
Juxta.prototype.run = function() {
	//
	setInterval($.proxy(this.route, this), 200);

	return this;
};

/**
 *
 */
Juxta.prototype.route = function() {
	//
	var hash = window.location.hash.replace(/#\/?/g, '').split('?'),
		query = hash[0].split('/'),
		paramsString = hash[1],
		params = [],
		pathParams = [],
		cid,
		action;

	function parseParamsString(str) {
		//
		var ret = {},
			seg = str.replace(/^\?/,'').split('&'),
			len = seg.length, i = 0, s;

		for (; i<len; i++) {
			if (!seg[i]) {
				continue;
			}
			s = seg[i].split('=');
			ret[decodeURIComponent(s[0])] = decodeURIComponent(s[1]);
		}

		return ret;
	}

	if (paramsString) {
		params = parseParamsString(paramsString);
	}

	if (/^\d+$/.test(query[0])) {
		cid = Number(query.shift());
	}

	if (query.length > 0) {
		action = query.pop();
		pathParams = query;
	}

	if (cid === undefined && action !== 'login') {
		this.redirect('login');
		return;
	}

	if (hash[0] != this._state) {
		switch (action) {
			case 'databases':
			case 'processlist':
			case 'users':
				this.explore({cid: cid, show: action});
				break;
			case 'status':
			case 'status-full':
			case 'variables':
			case 'charsets':
			case 'engines':
				this.info({cid: cid, show: action});
				break;
			case 'login':
				this._auth.show(params.id);
				break;
			//
			case 'tables':
			case 'views':
			case 'routines':
			case 'triggers':
				this.explore({cid: cid, show: action, from: pathParams[0]});
				break;
			//
			case 'browse':
				this.browser.browse({cid: cid, browse: pathParams[1], from: pathParams[0]});
				break;
			case 'sql':
				this.browser.sql({cid: cid, db: pathParams[0]});
				break;
			case 'columns':
				this._sidebar.highlight('columns', {'database': pathParams[0], 'table': pathParams[1]});
				this.table.edit({cid: cid, table: pathParams[1], from: pathParams[0]});
				break;
			case 'flush':
				this._cache.flush();
				this.redirect('databases', cid);
				return;
			default:
				this.redirect('databases', cid);
				return;
		}

		this._state = hash[0];
	}
};

/**
 * Change window title
 *
 * @param {Object} connection
 * @return {Juxta}
 */
Juxta.prototype._updateWindowTitle = function(connection) {
	//
	var title = '';

	if (connection) {
		//
		title = this._connection.get('name');

		if (!title) {
			title = connection.user + '@' +  connection.host;

			if (Number(connection.port) != Juxta.defaultPort) {
				title += ':' + connection.port;
			}
		}
	}

	window.document.title = (title ? title + ' - '  : '')  + 'Juxta';

	return this;
};

/**
 * Fix header links href attr
 *
 * @param {Object} connection
 * @return {Juxta}
 */
Juxta.prototype._repairHeaderLinks = function(connection) {
	//
	$('.header a[name]').each(function(i, link) {
		$(link).attr('href', '#/' + connection.cid + '/' + $(link).attr('name'));
	});

	return this;
};

/**
 * Show the appliaction
 *
 * @return {Juxta}
 */
Juxta.prototype.show = function() {
	$('#sidebar:not(.minimized)').slideDown(250);
	$('.float-box').hide();
	if ($('#applications').not(':visible')) {
		$('#applications').fadeIn(250);
		$('#header h1, #header .header-links').fadeIn(250);
	}

	return this;
};

/**
 * Hide
 *
 * @return {Juxta}
 */
Juxta.prototype.hide = function() {
	//
	$('#header h1, #header .header-links, #sidebar, #applications, .float-box, .context').hide();

	return this;
};

/**
 *
 */
Juxta.prototype.explore = function(params) {
	if (params.from) {
		this._sidebar.highlight(params.show, {'database': params.from});
		return this._explorer.explore(params);

	} else {
		this._sidebar.highlight(params.show);
		return this._explorer.explore(params);
	}
};

/**
 *
 */
Juxta.prototype.drop = function(params) {
	this._explorer.drop(params);
};

/**
 *
 */
Juxta.prototype.kill = function(params) {
	this._explorer.kill(params);
};

/**
 *
 */
Juxta.prototype.info = function(params) {
	this._sidebar.highlight('status');
	this.server.info(params);
};

/**
 * Notifications shortcuts
 */
Juxta.prototype.notify = function(message, options) {
	return this._notification.show(message, options);
};

/**
 *
 */
Juxta.prototype.loading = function(message, options) {
	return this._notification.loading(message, options);
};

/**
 *
 */
Juxta.prototype.error = function(message, options) {
	return this._notification.show(message, $.extend({}, {type: 'error', hide: false, fast: true}, options));
};

/**
 *
 */
Juxta.prototype.message = function(message, options) {
	this.messageBox.show(options, message);
};

/**
 *
 */
Juxta.prototype.about = function() {
	this.message($('#about').html(), {title: ''});
};

/**
 * Redirect
 *
 * @param {String} action
 * @param {Number} [cid] Connection ID
 * @return {Juxta}
 */
Juxta.prototype.redirect = function(action, cid) {
	//
	this._state = null;
	window.document.location.hash = '#/' + (typeof cid !== 'undefined' ? cid + '/' : '') + action;

	return this;
};

/**
 *
 * @param {Number} cid
 */
Juxta.prototype._changeConnectionCallback = function(cid) {
	//
	if (cid === undefined) {
		return;
	}

	var text = this._connection.get('name'),
		hide = this.hide,
		connectionsList = $('.header-connections');

	if (!text) {
		text = this._connection.get('user') + '@' + this._connection.get('host');

		if (Number(this._connection.get('port')) !== Juxta.defaultPort) {
			text += ':' + this._connection.get('port');
		}
	}

	$('.header-change-connection-link').text(text);

	this._updateWindowTitle(this._connection.get())
		._repairHeaderLinks(this._connection.get());

	connectionsList.empty();

	this._request.send({action: {get: 'connections'}, context: this, success: function(response) {
		$.each(response.connections, $.proxy(function(i, connection) {
			//
			var li = $('<li>').addClass('header-connection'),
				a = $('<a>');

			if (connection.cid == undefined) {
				a.attr('href', '#/login?id=' + connection.id);

			} else if (!this._connection.isCurrent(connection.cid)) {
				li.addClass('established');
				a.attr('href', '#/' + connection.cid + '/');

			} else {
				li.addClass('current');
			}

			if (a.attr('href')) {
				a.on('click', function() { hide(); } );
			}

			connectionsList.append(li.append(a.text(connection.name)));

		}, this));
	}});
};
<commit_msg>Fix for lint<commit_after>/*global document, window, setInterval */

/**
 * Juxta 0.0.1
 *
 * Copyright (c) 2010-2011 Alexey Golovnya
 * Licensed under the MIT license
 * http://juxta.ru
 */

/**
 * @class Juxta base application
 */
var Juxta = function() {

	var that = this;

	/**
	 * @type {String}
	 */
	this._state = null;

	/**
	 * @type Juxta.Cache
	 */
	this._cache = new Juxta.Cache();

	/**
	 * @type {Juxta.Connection}
	 */
	this._connection = new Juxta.Connection();

	/**
	 * @type {Juxta.Sidebar}
	 */
	this._sidebar = new Juxta.Sidebar(this._connection);

	/**
	 * Request/response
	 * @type Juxta.Request
	 */
	this._request = new Juxta.Request(this._connection, this._cache, {
		request: {
			beforeSend: function() {
				that.loading();
			},
			complete: function() {
				that.loading(false);
			},
			error: function(xhr, status) {
				if (status == 'parsererror') {
					that.error('Answer parsing error');
				} else {
					that.error(xhr.status + ' ' + xhr.statusText);
				}
			}
		},
		response: {
			connectionError: function(response) {
				that.error(response.error);
				that._auth.show();
			},
			sessionNotFound: function() {
				that.redirect('login');
			},
			error: function(response) {
				that.error(response.error);
			},
			unknowStatus: function() {
				that.error('Response with unknow status recived');
			}
		}
	});

	/**
	 * Notification messages
	 * @type {Juxta.Notification}
	 */
	this._notification = new Juxta.Notification();

	/**
	 * Server explorer
	 * @type {Juxta.Explorer}
	 */
	this._explorer = new Juxta.Explorer('#explorer', this._request);

	/**
	 * Table data browser
	 * @type {Juxta.Browser}
	 */
	this.browser = new Juxta.Browser('#data-browser', this._request);

	/**
	 * Table editor
	 * @type {Juxta.Table}
	 */
	this.table = new Juxta.Table('#table', this._request);

	/**
	 * Server inofrmation
	 * @type {Juxta.Server}
	 */
	this.server = new Juxta.Server('#server-info', this._request);

	/**
	 * Connect to server form
	 * @type {Juxta.Auth}
	 */
	this._auth = new Juxta.Auth('#login', this._request);

	/**
	 * Float box
	 * @type {Juxta.Modal}
	 */
	this.messageBox = new Juxta.Modal('#message');

	//
	$('.header-change-connection-link').on('click', function() {
		//
		var container = $('.header-connections-container'),
			list = container.find('.header-connections');

		container.css({right: ''}).toggle();

		if (container.is(':visible') && $('body').width() - container.offset().left < container.width()) {
			container.css({right: 7});
		}

		list.toggleClass('scroll', list.prop('scrollHeight') > list.prop('offsetHeight'));

		return false;
	});

	//
	this._connection.on('change', $.proxy(this._changeConnectionCallback, this));

	// Show Juxta when application ready to show
	$.each([this._explorer, this.server, this.browser, this.table], function(i, application) {
		application.on('ready', $.proxy(that.show, that));
	});

	//
	this._auth
		.on('before-show', $.proxy(function() {
			//
			this.hide()._updateWindowTitle();
			this._connection.reset();

		}, this))
		.on('login', function(connection) {
			that._connection.set(connection.cid, connection);
			that.redirect('databases', connection.cid);
		})
		.on('logout', function() {
			that._cache.flush();
			that._updateWindowTitle().redirect('login');
		})
		.on('change', function(cid) {
			that.redirect('', cid);
		});

	// Notifications
	this._auth.on('notify', function(message, type, options) {
		if (type === 'error') {
			that.error(message, options);
		} else if (type === 'loading') {
			that.loading(message, options);
		} else {
			that.notify(message, options);
		}
	});

	//
	$('#header a[name=about]').bind('click', function() {
		that.about();
		return false;
	});

	//
	$('#header .sql a').bind('click', function() {
		if (that.browser.is(':visible') && that.browser.mode == 'browse') {
			that.browser.toggleEditor();
			return false;
		}
	});

	$('#header a[name=logout]').click(function() {
		that._auth.logout();
		return false;
	});

	// @todo Remove this from here
	$('.float-box').draggable({scroll: false, handle: 'h3'});

	// @todo Remove this from here
	$(document.body).bind('click', function() {
		$('.context:visible').trigger('hide').hide();
	});

	this.run();

};

/**
 * Default MySQL port
 * @type {Number}
 */
Juxta.defaultPort = 3306;

/**
 * Run application
 * @return {Juxta}
 */
Juxta.prototype.run = function() {
	//
	setInterval($.proxy(this.route, this), 200);

	return this;
};

/**
 *
 */
Juxta.prototype.route = function() {
	//
	var hash = window.location.hash.replace(/#\/?/g, '').split('?'),
		query = hash[0].split('/'),
		paramsString = hash[1],
		params = [],
		pathParams = [],
		cid,
		action;

	function parseParamsString(str) {
		//
		var ret = {},
			seg = str.replace(/^\?/,'').split('&'),
			len = seg.length, i = 0, s;

		for (; i<len; i++) {
			if (!seg[i]) {
				continue;
			}
			s = seg[i].split('=');
			ret[decodeURIComponent(s[0])] = decodeURIComponent(s[1]);
		}

		return ret;
	}

	if (paramsString) {
		params = parseParamsString(paramsString);
	}

	if (/^\d+$/.test(query[0])) {
		cid = Number(query.shift());
	}

	if (query.length > 0) {
		action = query.pop();
		pathParams = query;
	}

	if (cid === undefined && action !== 'login') {
		this.redirect('login');
		return;
	}

	if (hash[0] != this._state) {
		switch (action) {
			case 'databases':
			case 'processlist':
			case 'users':
				this.explore({cid: cid, show: action});
				break;
			case 'status':
			case 'status-full':
			case 'variables':
			case 'charsets':
			case 'engines':
				this.info({cid: cid, show: action});
				break;
			case 'login':
				this._auth.show(params.id);
				break;
			//
			case 'tables':
			case 'views':
			case 'routines':
			case 'triggers':
				this.explore({cid: cid, show: action, from: pathParams[0]});
				break;
			//
			case 'browse':
				this.browser.browse({cid: cid, browse: pathParams[1], from: pathParams[0]});
				break;
			case 'sql':
				this.browser.sql({cid: cid, db: pathParams[0]});
				break;
			case 'columns':
				this._sidebar.highlight('columns', {'database': pathParams[0], 'table': pathParams[1]});
				this.table.edit({cid: cid, table: pathParams[1], from: pathParams[0]});
				break;
			case 'flush':
				this._cache.flush();
				this.redirect('databases', cid);
				return;
			default:
				this.redirect('databases', cid);
				return;
		}

		this._state = hash[0];
	}
};

/**
 * Change window title
 *
 * @param {Object} connection
 * @return {Juxta}
 */
Juxta.prototype._updateWindowTitle = function(connection) {
	//
	var title = '';

	if (connection) {
		//
		title = this._connection.get('name');

		if (!title) {
			title = connection.user + '@' +  connection.host;

			if (Number(connection.port) != Juxta.defaultPort) {
				title += ':' + connection.port;
			}
		}
	}

	window.document.title = (title ? title + ' - '  : '')  + 'Juxta';

	return this;
};

/**
 * Fix header links href attr
 *
 * @param {Object} connection
 * @return {Juxta}
 */
Juxta.prototype._repairHeaderLinks = function(connection) {
	//
	$('.header a[name]').each(function(i, link) {
		$(link).attr('href', '#/' + connection.cid + '/' + $(link).attr('name'));
	});

	return this;
};

/**
 * Show the appliaction
 *
 * @return {Juxta}
 */
Juxta.prototype.show = function() {
	$('#sidebar:not(.minimized)').slideDown(250);
	$('.float-box').hide();
	if ($('#applications').not(':visible')) {
		$('#applications').fadeIn(250);
		$('#header h1, #header .header-links').fadeIn(250);
	}

	return this;
};

/**
 * Hide
 *
 * @return {Juxta}
 */
Juxta.prototype.hide = function() {
	//
	$('#header h1, #header .header-links, #sidebar, #applications, .float-box, .context').hide();

	return this;
};

/**
 *
 */
Juxta.prototype.explore = function(params) {
	if (params.from) {
		this._sidebar.highlight(params.show, {'database': params.from});
		return this._explorer.explore(params);

	} else {
		this._sidebar.highlight(params.show);
		return this._explorer.explore(params);
	}
};

/**
 *
 */
Juxta.prototype.drop = function(params) {
	this._explorer.drop(params);
};

/**
 *
 */
Juxta.prototype.kill = function(params) {
	this._explorer.kill(params);
};

/**
 *
 */
Juxta.prototype.info = function(params) {
	this._sidebar.highlight('status');
	this.server.info(params);
};

/**
 * Notifications shortcuts
 */
Juxta.prototype.notify = function(message, options) {
	return this._notification.show(message, options);
};

/**
 *
 */
Juxta.prototype.loading = function(message, options) {
	return this._notification.loading(message, options);
};

/**
 *
 */
Juxta.prototype.error = function(message, options) {
	return this._notification.show(message, $.extend({}, {type: 'error', hide: false, fast: true}, options));
};

/**
 *
 */
Juxta.prototype.message = function(message, options) {
	this.messageBox.show(options, message);
};

/**
 *
 */
Juxta.prototype.about = function() {
	this.message($('#about').html(), {title: ''});
};

/**
 * Redirect
 *
 * @param {String} action
 * @param {Number} [cid] Connection ID
 * @return {Juxta}
 */
Juxta.prototype.redirect = function(action, cid) {
	//
	this._state = null;
	window.document.location.hash = '#/' + (typeof cid !== 'undefined' ? cid + '/' : '') + action;

	return this;
};

/**
 *
 * @param {Number} cid
 */
Juxta.prototype._changeConnectionCallback = function(cid) {
	//
	if (cid === undefined) {
		return;
	}

	var text = this._connection.get('name'),
		hide = this.hide,
		connectionsList = $('.header-connections');

	if (!text) {
		text = this._connection.get('user') + '@' + this._connection.get('host');

		if (Number(this._connection.get('port')) !== Juxta.defaultPort) {
			text += ':' + this._connection.get('port');
		}
	}

	$('.header-change-connection-link').text(text);

	this._updateWindowTitle(this._connection.get())
		._repairHeaderLinks(this._connection.get());

	connectionsList.empty();

	this._request.send({action: {get: 'connections'}, context: this, success: function(response) {
		$.each(response.connections, $.proxy(function(i, connection) {
			//
			var li = $('<li>').addClass('header-connection'),
				a = $('<a>');

			if (connection.cid === undefined) {
				a.attr('href', '#/login?id=' + connection.id);

			} else if (!this._connection.isCurrent(connection.cid)) {
				li.addClass('established');
				a.attr('href', '#/' + connection.cid + '/');

			} else {
				li.addClass('current');
			}

			if (a.attr('href')) {
				a.on('click', function() { hide(); } );
			}

			connectionsList.append(li.append(a.text(connection.name)));

		}, this));
	}});
};
<|endoftext|>


<commit_before>dojo.require("dojo.io.script");
dojo.require("dojox.dtl.dom");

dojo.require("dojox.dtl.tag.loader");
dojo.require("dojox.dtl.tag.logic");
dojo.require("dojox.dtl.tag.loop");
dojo.require("dojox.dtl.filter.lists");
dojo.require("dojox.dtl.tag.logic");
dojo.require("dojox.dtl.filter.dates");
dojo.require("dojox.dtl.utils.date");
dojo.require("dojox.dtl.filter.strings");
dojo.require("dojox.dtl.filter.htmlstrings");

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

// Twitter date filter
dojo.provide("uxebu.dtl.filter");
dojo.require("dojo.date.locale");

uxebu.dtl.filter = {
	ago: function(value, arg){
		// summary:
		//		Simple filter for twitter style display of timestamp

		var	postDate = new Date(value),
			today = new Date(),
			yesterday = dojo.date.add(today, "day", -1),
			postStr;

		yesterday.setHours(23);
		yesterday.setMinutes(59);
		yesterday.setSeconds(59);
		if (postDate <= yesterday){
			postStr = dojo.date.locale.format(postDate);
		}else{
			var diff = dojo.date.difference(postDate, today, "minute"),
				diffObj;

			if (diff > 59){
				diff = Math.round(diff/60);
				diffObj = {
					diff: "about " + diff,
					unit: diff > 1 ? "hours" : "hour"
				};
			}else if (diff > 0){
				diffObj = {
					diff: diff,
					unit: diff > 1 ? "minutes" : "minute"
				};
			}else{
				diffObj = {
					diff: "",
					unit: "just a moment"
				};
			}
			postStr = diffObj.diff + " " + diffObj.unit + " ago";
		}
		return postStr;
	}
}

dojo.ready(function(){
	dojox.dtl.register.filters("uxebu.dtl", {"filter": ["ago"]});

	dojo.provide("learn");
	learn = {
		templates: {
			loader: '

',
			noResults: '

No more results, maybe watch some videos on one of the previous pages, they rock.

',
			about: '

Hi there,
learnjs is a simple Q&A tool by uxebu based on twitter and vimeo.
Simply ask a JavaScript question or provide an answer in a one minute, max. five lines of code video.

If you are interested in making it better or using it in your own environment,
clone/fork the repository at github, or send us a message via twitter (@uxebu) or our website
Background image curtesy of ChicagoGeek

<button class="button" onclick="uxebu.widget.popup.hide();">Close</button>

',
			questions: '{% if not questions|length %}

Hey, no js questions? Just ask one by sending a tweet to @learnjs

{% endif %}{% for q in questions %}

{{ q.text|safe }}
{{ q.created_at|ago }} by {{ q.from_user }}

{% endfor %}',
			answers: '{% for a in answers %}

{{ a.video.title }}
{{ a.video.upload_date|ago }} by {{ a.video.user_name }}
{{ a.video.html|safe }}

{% endfor %}',
			questionPostConfirm: '

Thank you, it might take a few seconds (up to a minute in bad twitter times) until your question has reached the wise ninjas of the interpipes.
If the question doesn\'t show up straight away, just press the reload button a few times.

<button class="button" onclick="uxebu.widget.popup.hide(); learn.getQuestions();">Close</button>

',
		},
		config: {
			limit: 5,
			offset: 1
		},
		currentTab: 0,
		init: function(){
			// summary:
			//		Initializes learnjs

			// Setting up page navigation
			dojo.query(".menu > .about").onclick(function(e){
				dojo.stopEvent(e);
				uxebu.widget.popup.show(learn.templates.about);
			});

			// Parse margin and nomargin loader
			var loaderTempl = new dojox.dtl.Template(learn.templates.loader);
			learn.templates.loaderMargin = loaderTempl.render(new dojox.dtl.Context({marginRight: "marginRight"}));
			learn.templates.loaderNoMargin = loaderTempl.render(new dojox.dtl.Context({marginRight: ""}));

			learn.nodeLists = {
				buttonPrev: dojo.query(".button.previous"),
				buttonNext: dojo.query(".button.next"),
				pageNo: dojo.query(".pageNo"),
				tabs: dojo.query(".tab"),
				tabContents: dojo.query(".tabContents")
			}

			// Set up tabs
			learn.nodeLists.tabs.connect("onclick", function(e){
				var node = e.target;
				while (!dojo.hasClass(node, "tab")){
					node = node.parentNode;
				}

				var index = dojo.indexOf(learn.nodeLists.tabs, node);
				if (index != learn.currentTab){
					learn.skip(index);
				}
			});

			// Connect to search box to auto search on enter
			dojo.query(".search").connect("onkeydown", function(e){
				if (e.keyCode == dojo.keys.ENTER){
					learn.getAnswers();
				}
			});

			learn.getQuestions();
			learn.getAnswers();
		},
		skip: function(index){
			// summary:
			//		Handles skipping to a different tab.

			dojo.removeClass(learn.nodeLists.tabs[learn.currentTab], "active");
			dojo.addClass(learn.nodeLists.tabContents[learn.currentTab], "displayNone");
			learn.currentTab = index;
			dojo.removeClass(learn.nodeLists.tabContents[learn.currentTab], "displayNone");
			dojo.addClass(learn.nodeLists.tabs[learn.currentTab], "active");
		},
		getQuestions: function(){
			// summary:
			//		Gets latest tweets.

			dojo.byId("questions").innerHTML = learn.templates.loaderNoMargin;
			dojo.io.script.get({
				url: "http://search.twitter.com/search.json?q=learnjs", // With questionmark +%3F
				jsonp: "callback",
				load: function(data){
					if (data.results){
						learn.renderQuestions(data.results);
					}
				}
			});
		},
		renderQuestions: function(questions){
			// summary:
			//		Renders questions and twitter feed in general.

			var 	tmpl = new dojox.dtl.Template(learn.templates.questions),
				node = dojo.byId("questions");

			node.innerHTML = ""; // FIXME?!!!
			var context = new dojox.dtl.Context({questions: questions});
			node.appendChild(dojo._toDom(tmpl.render(context)));
		},
		getAnswers: function(type, search){
			// summary:
			//		Gets new answers from yql table.

			switch (type){
				case 'next':
					learn.config.offset += learn.config.limit;
					break;
				case 'prev':
					if (learn.config.offset > 1){
						learn.config.offset -= learn.config.limit;
					}
					break;
			}

			// If search input has a value we make a search is provided we make a search, otherwise list all
			var search = dojo.byId("search").value;
			if (search){
				// Reset counter on first search
				if (!learn.searchReset){
					learn.config.offset = 1;
					learn.config.limit = 5;
					learn.searchReset = true;
				}
				var url = "http://query.yahooapis.com/v1/public/yql?q=use%20%22http%3A%2F%2Flearnjs.org%2Fyql%2Fvideosearch.xml%22%20as%20videos%3B%20select%20*%20from%20videos%20where%20search%3D%22"+search+"%22%20limit%20"+learn.config.limit+"%20offset%20"+learn.config.offset+"&format=json&_maxage=3600&_rnd=20100802";
			}else{
				// Reset counter on first blank lookup
				if (learn.searchReset){
					learn.config.offset = 1;
					learn.config.limit = 5;
				}
				learn.searchReset = false;
				var url = "http://query.yahooapis.com/v1/public/yql?q=use%20%22http%3A%2F%2Flearnjs.org%2Fyql%2Fvideos.xml%22%20as%20videos%3B%20select%20*%20from%20videos%20limit%20"+learn.config.limit+"%20offset%20"+learn.config.offset+"&format=json&_maxage=3600&_rnd=20100803";
			}

			dojo.byId("answers").innerHTML = learn.templates.loaderMargin;
			dojo.io.script.get({
				url: url,
				jsonp: "callback",
				load: function(data){
					// YQL has a weird bug where it resurns an object when resultset is one.
					if (data.query.count == 1 && data.query.results.videos.video){
						var video = data.query.results.videos.video;
						data.query.results.videos = [{ video: data.query.results.videos.video }];
					}
					if (data.query.count == 0){
						learn.nodeLists.buttonNext.attr("disabled", true);
						if (learn.config.offset > 1){
							learn.nodeLists.buttonPrev.attr("disabled", false);
						}

						dojo.byId("answers").innerHTML = learn.templates.noResults;
					}else{
						// Disable next button if resultset < limit
						learn.nodeLists.buttonNext.attr("disabled", data.query.count < learn.config.limit);
						learn.nodeLists.buttonPrev.attr("disabled", !(learn.config.offset > 1));

						learn.renderAnswers(data.query.results.videos);
					}

					learn.nodeLists.pageNo.attr("innerHTML", (learn.config.offset+learn.config.limit-1)/learn.config.limit)
				}
			});
		},
		renderAnswers: function(answers){
			// summary:
			//		Renders available video answers from yql table.

			var	tmpl = new dojox.dtl.Template(learn.templates.answers),
				node = dojo.byId("answers");

			node.innerHTML = ""; // FIXME?!!!

			var context = new dojox.dtl.Context({
				answers: answers
			});
			node.appendChild(dojo._toDom(tmpl.render(context)));
		}
	}

	learn.init();
});<commit_msg>Added search min word length<commit_after>dojo.require("dojo.io.script");
dojo.require("dojox.dtl.dom");

dojo.require("dojox.dtl.tag.loader");
dojo.require("dojox.dtl.tag.logic");
dojo.require("dojox.dtl.tag.loop");
dojo.require("dojox.dtl.filter.lists");
dojo.require("dojox.dtl.tag.logic");
dojo.require("dojox.dtl.filter.dates");
dojo.require("dojox.dtl.utils.date");
dojo.require("dojox.dtl.filter.strings");
dojo.require("dojox.dtl.filter.htmlstrings");

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

// Twitter date filter
dojo.provide("uxebu.dtl.filter");
dojo.require("dojo.date.locale");

uxebu.dtl.filter = {
	ago: function(value, arg){
		// summary:
		//		Simple filter for twitter style display of timestamp

		var	postDate = new Date(value),
			today = new Date(),
			yesterday = dojo.date.add(today, "day", -1),
			postStr;

		yesterday.setHours(23);
		yesterday.setMinutes(59);
		yesterday.setSeconds(59);
		if (postDate <= yesterday){
			postStr = dojo.date.locale.format(postDate);
		}else{
			var diff = dojo.date.difference(postDate, today, "minute"),
				diffObj;

			if (diff > 59){
				diff = Math.round(diff/60);
				diffObj = {
					diff: "about " + diff,
					unit: diff > 1 ? "hours" : "hour"
				};
			}else if (diff > 0){
				diffObj = {
					diff: diff,
					unit: diff > 1 ? "minutes" : "minute"
				};
			}else{
				diffObj = {
					diff: "",
					unit: "just a moment"
				};
			}
			postStr = diffObj.diff + " " + diffObj.unit + " ago";
		}
		return postStr;
	}
}

dojo.ready(function(){
	dojox.dtl.register.filters("uxebu.dtl", {"filter": ["ago"]});

	dojo.provide("learn");
	learn = {
		templates: {
			loader: '

',
			noResults: '

No more results, maybe watch some videos on one of the previous pages, they rock.

',
			about: '

Hi there,
learnjs is a simple Q&A tool by uxebu based on twitter and vimeo.
Simply ask a JavaScript question or provide an answer in a one minute, max. five lines of code video.

If you are interested in making it better or using it in your own environment,
clone/fork the repository at github, or send us a message via twitter (@uxebu) or our website
Background image curtesy of ChicagoGeek

<button class="button" onclick="uxebu.widget.popup.hide();">Close</button>

',
			questions: '{% if not questions|length %}

Hey, no js questions? Just ask one by sending a tweet to @learnjs

{% endif %}{% for q in questions %}

{{ q.text|safe }}
{{ q.created_at|ago }} by {{ q.from_user }}

{% endfor %}',
			answers: '{% for a in answers %}

{{ a.video.title }}
{{ a.video.upload_date|ago }} by {{ a.video.user_name }}
{{ a.video.html|safe }}

{% endfor %}',
			questionPostConfirm: '

Thank you, it might take a few seconds (up to a minute in bad twitter times) until your question has reached the wise ninjas of the interpipes.
If the question doesn\'t show up straight away, just press the reload button a few times.

<button class="button" onclick="uxebu.widget.popup.hide(); learn.getQuestions();">Close</button>

',
		},
		config: {
			limit: 5,
			offset: 1
		},
		currentTab: 0,
		init: function(){
			// summary:
			//		Initializes learnjs

			// Setting up page navigation
			dojo.query(".menu > .about").onclick(function(e){
				dojo.stopEvent(e);
				uxebu.widget.popup.show(learn.templates.about);
			});

			// Parse margin and nomargin loader
			var loaderTempl = new dojox.dtl.Template(learn.templates.loader);
			learn.templates.loaderMargin = loaderTempl.render(new dojox.dtl.Context({marginRight: "marginRight"}));
			learn.templates.loaderNoMargin = loaderTempl.render(new dojox.dtl.Context({marginRight: ""}));

			learn.nodeLists = {
				buttonPrev: dojo.query(".button.previous"),
				buttonNext: dojo.query(".button.next"),
				pageNo: dojo.query(".pageNo"),
				tabs: dojo.query(".tab"),
				tabContents: dojo.query(".tabContents")
			}

			// Set up tabs
			learn.nodeLists.tabs.connect("onclick", function(e){
				var node = e.target;
				while (!dojo.hasClass(node, "tab")){
					node = node.parentNode;
				}

				var index = dojo.indexOf(learn.nodeLists.tabs, node);
				if (index != learn.currentTab){
					learn.skip(index);
				}
			});

			// Connect to search box to auto search on enter
			dojo.query(".search").connect("onkeydown", function(e){
				if (e.keyCode == dojo.keys.ENTER){
					learn.getAnswers();
				}
			});

			learn.getQuestions();
			learn.getAnswers();
		},
		skip: function(index){
			// summary:
			//		Handles skipping to a different tab.

			dojo.removeClass(learn.nodeLists.tabs[learn.currentTab], "active");
			dojo.addClass(learn.nodeLists.tabContents[learn.currentTab], "displayNone");
			learn.currentTab = index;
			dojo.removeClass(learn.nodeLists.tabContents[learn.currentTab], "displayNone");
			dojo.addClass(learn.nodeLists.tabs[learn.currentTab], "active");
		},
		getQuestions: function(){
			// summary:
			//		Gets latest tweets.

			dojo.byId("questions").innerHTML = learn.templates.loaderNoMargin;
			dojo.io.script.get({
				url: "http://search.twitter.com/search.json?q=learnjs", // With questionmark +%3F
				jsonp: "callback",
				load: function(data){
					if (data.results){
						learn.renderQuestions(data.results);
					}
				}
			});
		},
		renderQuestions: function(questions){
			// summary:
			//		Renders questions and twitter feed in general.

			var 	tmpl = new dojox.dtl.Template(learn.templates.questions),
				node = dojo.byId("questions");

			node.innerHTML = ""; // FIXME?!!!
			var context = new dojox.dtl.Context({questions: questions});
			node.appendChild(dojo._toDom(tmpl.render(context)));
		},
		getAnswers: function(type, search){
			// summary:
			//		Gets new answers from yql table.

			switch (type){
				case 'next':
					learn.config.offset += learn.config.limit;
					break;
				case 'prev':
					if (learn.config.offset > 1){
						learn.config.offset -= learn.config.limit;
					}
					break;
			}

			// If search input has a value we make a search is provided we make a search, otherwise list all
			var search = dojo.byId("search").value;
			if (search && search.length > 2){
				// Reset counter on first search
				if (!learn.searchReset){
					learn.config.offset = 1;
					learn.config.limit = 5;
					learn.searchReset = true;
				}
				var url = "http://query.yahooapis.com/v1/public/yql?q=use%20%22http%3A%2F%2Flearnjs.org%2Fyql%2Fvideosearch.xml%22%20as%20videos%3B%20select%20*%20from%20videos%20where%20search%3D%22"+search+"%22%20limit%20"+learn.config.limit+"%20offset%20"+learn.config.offset+"&format=json&_maxage=3600&_rnd=20100802";
			}else{
				// Display alert when search term is only 2 characters long
				if (search && search.length <= 2){
					alert("Search phrase needs to be at least three characters long");
				}
				// Reset counter on first blank lookup
				if (learn.searchReset){
					learn.config.offset = 1;
					learn.config.limit = 5;
				}
				learn.searchReset = false;
				var url = "http://query.yahooapis.com/v1/public/yql?q=use%20%22http%3A%2F%2Flearnjs.org%2Fyql%2Fvideos.xml%22%20as%20videos%3B%20select%20*%20from%20videos%20limit%20"+learn.config.limit+"%20offset%20"+learn.config.offset+"&format=json&_maxage=3600&_rnd=20100803";
			}

			dojo.byId("answers").innerHTML = learn.templates.loaderMargin;
			dojo.io.script.get({
				url: url,
				jsonp: "callback",
				load: function(data){
					// YQL has a weird bug where it resurns an object when resultset is one.
					if (data.query.count == 1 && data.query.results.videos.video){
						var video = data.query.results.videos.video;
						data.query.results.videos = [{ video: data.query.results.videos.video }];
					}
					if (data.query.count == 0){
						learn.nodeLists.buttonNext.attr("disabled", true);
						if (learn.config.offset > 1){
							learn.nodeLists.buttonPrev.attr("disabled", false);
						}

						dojo.byId("answers").innerHTML = learn.templates.noResults;
					}else{
						// Disable next button if resultset < limit
						learn.nodeLists.buttonNext.attr("disabled", data.query.count < learn.config.limit);
						learn.nodeLists.buttonPrev.attr("disabled", !(learn.config.offset > 1));

						learn.renderAnswers(data.query.results.videos);
					}

					learn.nodeLists.pageNo.attr("innerHTML", (learn.config.offset+learn.config.limit-1)/learn.config.limit)
				}
			});
		},
		renderAnswers: function(answers){
			// summary:
			//		Renders available video answers from yql table.

			var	tmpl = new dojox.dtl.Template(learn.templates.answers),
				node = dojo.byId("answers");

			node.innerHTML = ""; // FIXME?!!!

			var context = new dojox.dtl.Context({
				answers: answers
			});
			node.appendChild(dojo._toDom(tmpl.render(context)));
		}
	}

	learn.init();
});<|endoftext|>


<commit_before>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');

//  ---------------------------------------------------------------------------

module.exports = class lykke extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'lykke',
            'name': 'Lykke',
            'countries': 'CH',
            'version': 'v1',
            'rateLimit': 200,
            'has': {
                'CORS': false,
                'fetchOHLCV': false,
                'fetchTrades': false,
                'fetchOpenOrders': true,
                'fetchClosedOrders': true,
                'fetchOrders': true,
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': false,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/34487620-3139a7b0-efe6-11e7-90f5-e520cef74451.jpg',
                'api': {
                    'mobile': 'https://api.lykkex.com/api',
                    'public': 'https://hft-api.lykke.com/api',
                    'private': 'https://hft-api.lykke.com/api',
                    'test': {
                        'mobile': 'https://api.lykkex.com/api',
                        'public': 'https://hft-service-dev.lykkex.net/api',
                        'private': 'https://hft-service-dev.lykkex.net/api',
                    },
                },
                'www': 'https://www.lykke.com',
                'doc': [
                    'https://hft-api.lykke.com/swagger/ui/',
                    'https://www.lykke.com/lykke_api',
                ],
                'fees': 'https://www.lykke.com/trading-conditions',
            },
            'api': {
                'mobile': {
                    'get': [
                        'AllAssetPairRates/{market}',
                    ],
                },
                'public': {
                    'get': [
                        'AssetPairs',
                        'AssetPairs/{id}',
                        'IsAlive',
                        'OrderBooks',
                        'OrderBooks/{AssetPairId}',
                    ],
                },
                'private': {
                    'get': [
                        'Orders',
                        'Orders/{id}',
                        'Wallets',
                    ],
                    'post': [
                        'Orders/limit',
                        'Orders/market',
                        'Orders/{id}/Cancel',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'maker': 0.0, // as of 7 Feb 2018, see https://github.com/ccxt/ccxt/issues/1863
                    'taker': 0.0, // https://www.lykke.com/cp/wallet-fees-and-limits
                },
                'funding': {
                    'tierBased': false,
                    'percentage': false,
                    'withdraw': {
                        'BTC': 0.001,
                    },
                    'deposit': {
                        'BTC': 0,
                    },
                },
            },
        });
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetWallets ();
        let result = { 'info': balances };
        for (let i = 0; i < balances.length; i++) {
            let balance = balances[i];
            let currency = balance['AssetId'];
            let total = balance['Balance'];
            let used = balance['Reserved'];
            let free = total - used;
            result[currency] = {
                'free': free,
                'used': used,
                'total': total,
            };
        }
        return this.parseBalance (result);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        return await this.privatePostOrdersIdCancel ({ 'id': id });
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let query = {
            'AssetPairId': market['id'],
            'OrderAction': this.capitalize (side),
            'Volume': amount,
        };
        if (type === 'market') {
            query['Asset'] = (side === 'buy') ? market['base'] : market['quote'];
        } else if (type === 'limit') {
            query['Price'] = price;
        }
        let method = 'privatePostOrders' + this.capitalize (type);
        let result = await this[method] (this.extend (query, params));
        return {
            'id': undefined,
            'info': result,
        };
    }

    async fetchMarkets () {
        let markets = await this.publicGetAssetPairs ();
        let result = [];
        for (let i = 0; i < markets.length; i++) {
            let market = markets[i];
            let id = market['Id'];
            let base = market['BaseAssetId'];
            let quote = market['QuotingAssetId'];
            base = this.commonCurrencyCode (base);
            quote = this.commonCurrencyCode (quote);
            let symbol = market['Name'];
            let precision = {
                'amount': market['Accuracy'],
                'price': market['InvertedAccuracy'],
            };
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'active': true,
                'info': market,
                'lot': Math.pow (10, -precision['amount']),
                'precision': precision,
                'limits': {
                    'amount': {
                        'min': Math.pow (10, -precision['amount']),
                        'max': Math.pow (10, precision['amount']),
                    },
                    'price': {
                        'min': Math.pow (10, -precision['price']),
                        'max': Math.pow (10, precision['price']),
                    },
                },
            });
        }
        return result;
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = this.milliseconds ();
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        ticker = ticker['Result'];
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': undefined,
            'low': undefined,
            'bid': parseFloat (ticker['Rate']['Bid']),
            'bidVolume': undefined,
            'ask': parseFloat (ticker['Rate']['Ask']),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'last': undefined,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': undefined,
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let ticker = await this.mobileGetAllAssetPairRatesMarket (this.extend ({
            'market': market['id'],
        }, params));
        return this.parseTicker (ticker, market);
    }

    parseOrderStatus (status) {
        if (status === 'Pending') {
            return 'open';
        } else if (status === 'InOrderBook') {
            return 'open';
        } else if (status === 'Processing') {
            return 'open';
        } else if (status === 'Matched') {
            return 'closed';
        } else if (status === 'Cancelled') {
            return 'canceled';
        } else if (status === 'NotEnoughFunds') {
            return 'NotEnoughFunds';
        } else if (status === 'NoLiquidity') {
            return 'NoLiquidity';
        } else if (status === 'UnknownAsset') {
            return 'UnknownAsset';
        } else if (status === 'LeadToNegativeSpread') {
            return 'LeadToNegativeSpread';
        }
        return status;
    }

    parseOrder (order, market = undefined) {
        let status = this.parseOrderStatus (order['Status']);
        let symbol = undefined;
        if (!market) {
            if ('AssetPairId' in order)
                if (order['AssetPairId'] in this.markets_by_id)
                    market = this.markets_by_id[order['AssetPairId']];
        }
        if (market)
            symbol = market['symbol'];
        let timestamp = undefined;
        if ('LastMatchTime' in order) {
            timestamp = this.parse8601 (order['LastMatchTime']);
        } else if ('Registered' in order) {
            timestamp = this.parse8601 (order['Registered']);
        } else if ('CreatedAt' in order) {
            timestamp = this.parse8601 (order['CreatedAt']);
        }
        let price = this.safeFloat (order, 'Price');
        let amount = this.safeFloat (order, 'Volume');
        let remaining = this.safeFloat (order, 'RemainingVolume');
        let filled = amount - remaining;
        let cost = filled * price;
        let result = {
            'info': order,
            'id': order['Id'],
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'type': undefined,
            'side': undefined,
            'price': price,
            'cost': cost,
            'average': undefined,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'status': status,
            'fee': undefined,
        };
        return result;
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        let response = await this.privateGetOrdersId (this.extend ({
            'id': id,
        }, params));
        return this.parseOrder (response);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let response = await this.privateGetOrders ();
        return this.parseOrders (response, undefined, since, limit);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let response = await this.privateGetOrders (this.extend ({
            'status': 'InOrderBook',
        }, params));
        return this.parseOrders (response, undefined, since, limit);
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let response = await this.privateGetOrders (this.extend ({
            'status': 'Matched',
        }, params));
        return this.parseOrders (response, undefined, since, limit);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let response = await this.publicGetOrderBooksAssetPairId (this.extend ({
            'AssetPairId': this.marketId (symbol),
        }, params));
        let orderbook = {
            'timestamp': undefined,
            'bids': [],
            'asks': [],
        };
        let timestamp = undefined;
        for (let i = 0; i < response.length; i++) {
            let side = response[i];
            if (side['IsBuy']) {
                orderbook['bids'] = this.arrayConcat (orderbook['bids'], side['Prices']);
            } else {
                orderbook['asks'] = this.arrayConcat (orderbook['asks'], side['Prices']);
            }
            let sideTimestamp = this.parse8601 (side['Timestamp']);
            timestamp = (typeof timestamp === 'undefined') ? sideTimestamp : Math.max (timestamp, sideTimestamp);
        }
        return this.parseOrderBook (orderbook, timestamp, 'bids', 'asks', 'Price', 'Volume');
    }

    parseBidAsk (bidask, priceKey = 0, amountKey = 1) {
        let price = parseFloat (bidask[priceKey]);
        let amount = parseFloat (bidask[amountKey]);
        if (amount < 0)
            amount = -amount;
        return [ price, amount ];
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'][api] + '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (api === 'public') {
            if (Object.keys (query).length)
                url += '?' + this.urlencode (query);
        } else if (api === 'private') {
            if (method === 'GET')
                if (Object.keys (query).length)
                    url += '?' + this.urlencode (query);
            this.checkRequiredCredentials ();
            headers = {
                'api-key': this.apiKey,
                'Accept': 'application/json',
                'Content-Type': 'application/json',
            };
            if (method === 'POST')
                if (Object.keys (params).length)
                    body = this.json (params);
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<commit_msg>lykke parseOrder timestamp conversion python3 fix #2492<commit_after>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');

//  ---------------------------------------------------------------------------

module.exports = class lykke extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'lykke',
            'name': 'Lykke',
            'countries': 'CH',
            'version': 'v1',
            'rateLimit': 200,
            'has': {
                'CORS': false,
                'fetchOHLCV': false,
                'fetchTrades': false,
                'fetchOpenOrders': true,
                'fetchClosedOrders': true,
                'fetchOrders': true,
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': false,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/34487620-3139a7b0-efe6-11e7-90f5-e520cef74451.jpg',
                'api': {
                    'mobile': 'https://api.lykkex.com/api',
                    'public': 'https://hft-api.lykke.com/api',
                    'private': 'https://hft-api.lykke.com/api',
                    'test': {
                        'mobile': 'https://api.lykkex.com/api',
                        'public': 'https://hft-service-dev.lykkex.net/api',
                        'private': 'https://hft-service-dev.lykkex.net/api',
                    },
                },
                'www': 'https://www.lykke.com',
                'doc': [
                    'https://hft-api.lykke.com/swagger/ui/',
                    'https://www.lykke.com/lykke_api',
                ],
                'fees': 'https://www.lykke.com/trading-conditions',
            },
            'api': {
                'mobile': {
                    'get': [
                        'AllAssetPairRates/{market}',
                    ],
                },
                'public': {
                    'get': [
                        'AssetPairs',
                        'AssetPairs/{id}',
                        'IsAlive',
                        'OrderBooks',
                        'OrderBooks/{AssetPairId}',
                    ],
                },
                'private': {
                    'get': [
                        'Orders',
                        'Orders/{id}',
                        'Wallets',
                    ],
                    'post': [
                        'Orders/limit',
                        'Orders/market',
                        'Orders/{id}/Cancel',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'maker': 0.0, // as of 7 Feb 2018, see https://github.com/ccxt/ccxt/issues/1863
                    'taker': 0.0, // https://www.lykke.com/cp/wallet-fees-and-limits
                },
                'funding': {
                    'tierBased': false,
                    'percentage': false,
                    'withdraw': {
                        'BTC': 0.001,
                    },
                    'deposit': {
                        'BTC': 0,
                    },
                },
            },
        });
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetWallets ();
        let result = { 'info': balances };
        for (let i = 0; i < balances.length; i++) {
            let balance = balances[i];
            let currency = balance['AssetId'];
            let total = balance['Balance'];
            let used = balance['Reserved'];
            let free = total - used;
            result[currency] = {
                'free': free,
                'used': used,
                'total': total,
            };
        }
        return this.parseBalance (result);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        return await this.privatePostOrdersIdCancel ({ 'id': id });
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let query = {
            'AssetPairId': market['id'],
            'OrderAction': this.capitalize (side),
            'Volume': amount,
        };
        if (type === 'market') {
            query['Asset'] = (side === 'buy') ? market['base'] : market['quote'];
        } else if (type === 'limit') {
            query['Price'] = price;
        }
        let method = 'privatePostOrders' + this.capitalize (type);
        let result = await this[method] (this.extend (query, params));
        return {
            'id': undefined,
            'info': result,
        };
    }

    async fetchMarkets () {
        let markets = await this.publicGetAssetPairs ();
        let result = [];
        for (let i = 0; i < markets.length; i++) {
            let market = markets[i];
            let id = market['Id'];
            let base = market['BaseAssetId'];
            let quote = market['QuotingAssetId'];
            base = this.commonCurrencyCode (base);
            quote = this.commonCurrencyCode (quote);
            let symbol = market['Name'];
            let precision = {
                'amount': market['Accuracy'],
                'price': market['InvertedAccuracy'],
            };
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'active': true,
                'info': market,
                'lot': Math.pow (10, -precision['amount']),
                'precision': precision,
                'limits': {
                    'amount': {
                        'min': Math.pow (10, -precision['amount']),
                        'max': Math.pow (10, precision['amount']),
                    },
                    'price': {
                        'min': Math.pow (10, -precision['price']),
                        'max': Math.pow (10, precision['price']),
                    },
                },
            });
        }
        return result;
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = this.milliseconds ();
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        ticker = ticker['Result'];
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': undefined,
            'low': undefined,
            'bid': parseFloat (ticker['Rate']['Bid']),
            'bidVolume': undefined,
            'ask': parseFloat (ticker['Rate']['Ask']),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'last': undefined,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': undefined,
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let ticker = await this.mobileGetAllAssetPairRatesMarket (this.extend ({
            'market': market['id'],
        }, params));
        return this.parseTicker (ticker, market);
    }

    parseOrderStatus (status) {
        if (status === 'Pending') {
            return 'open';
        } else if (status === 'InOrderBook') {
            return 'open';
        } else if (status === 'Processing') {
            return 'open';
        } else if (status === 'Matched') {
            return 'closed';
        } else if (status === 'Cancelled') {
            return 'canceled';
        } else if (status === 'NotEnoughFunds') {
            return 'NotEnoughFunds';
        } else if (status === 'NoLiquidity') {
            return 'NoLiquidity';
        } else if (status === 'UnknownAsset') {
            return 'UnknownAsset';
        } else if (status === 'LeadToNegativeSpread') {
            return 'LeadToNegativeSpread';
        }
        return status;
    }

    parseOrder (order, market = undefined) {
        let status = this.parseOrderStatus (order['Status']);
        let symbol = undefined;
        if (!market) {
            if ('AssetPairId' in order)
                if (order['AssetPairId'] in this.markets_by_id)
                    market = this.markets_by_id[order['AssetPairId']];
        }
        if (market)
            symbol = market['symbol'];
        let timestamp = undefined;
        if ('LastMatchTime' in order) {
            if (order['LastMatchTime'])
                timestamp = this.parse8601 (order['LastMatchTime']);
        } else if ('Registered' in order) {
            if (order['Registered'])
                timestamp = this.parse8601 (order['Registered']);
        } else if ('CreatedAt' in order) {
            if (order['CreatedAt'])
                timestamp = this.parse8601 (order['CreatedAt']);
        }
        let price = this.safeFloat (order, 'Price');
        let amount = this.safeFloat (order, 'Volume');
        let remaining = this.safeFloat (order, 'RemainingVolume');
        let filled = amount - remaining;
        let cost = filled * price;
        let result = {
            'info': order,
            'id': order['Id'],
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'type': undefined,
            'side': undefined,
            'price': price,
            'cost': cost,
            'average': undefined,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'status': status,
            'fee': undefined,
        };
        return result;
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        let response = await this.privateGetOrdersId (this.extend ({
            'id': id,
        }, params));
        return this.parseOrder (response);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let response = await this.privateGetOrders ();
        return this.parseOrders (response, undefined, since, limit);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let response = await this.privateGetOrders (this.extend ({
            'status': 'InOrderBook',
        }, params));
        return this.parseOrders (response, undefined, since, limit);
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let response = await this.privateGetOrders (this.extend ({
            'status': 'Matched',
        }, params));
        return this.parseOrders (response, undefined, since, limit);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let response = await this.publicGetOrderBooksAssetPairId (this.extend ({
            'AssetPairId': this.marketId (symbol),
        }, params));
        let orderbook = {
            'timestamp': undefined,
            'bids': [],
            'asks': [],
        };
        let timestamp = undefined;
        for (let i = 0; i < response.length; i++) {
            let side = response[i];
            if (side['IsBuy']) {
                orderbook['bids'] = this.arrayConcat (orderbook['bids'], side['Prices']);
            } else {
                orderbook['asks'] = this.arrayConcat (orderbook['asks'], side['Prices']);
            }
            let sideTimestamp = this.parse8601 (side['Timestamp']);
            timestamp = (typeof timestamp === 'undefined') ? sideTimestamp : Math.max (timestamp, sideTimestamp);
        }
        return this.parseOrderBook (orderbook, timestamp, 'bids', 'asks', 'Price', 'Volume');
    }

    parseBidAsk (bidask, priceKey = 0, amountKey = 1) {
        let price = parseFloat (bidask[priceKey]);
        let amount = parseFloat (bidask[amountKey]);
        if (amount < 0)
            amount = -amount;
        return [ price, amount ];
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'][api] + '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (api === 'public') {
            if (Object.keys (query).length)
                url += '?' + this.urlencode (query);
        } else if (api === 'private') {
            if (method === 'GET')
                if (Object.keys (query).length)
                    url += '?' + this.urlencode (query);
            this.checkRequiredCredentials ();
            headers = {
                'api-key': this.apiKey,
                'Accept': 'application/json',
                'Content-Type': 'application/json',
            };
            if (method === 'POST')
                if (Object.keys (params).length)
                    body = this.json (params);
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<|endoftext|>


<commit_before>/* eslint-disable no-undef, no-unused-vars */

const fs = require('fs');
const path = require('path');

const config = require('../config')();

const rootFolder = process.cwd();
const componentPath = path.join(config.appFolder, config.componentsFolder);

const getData = (componentName, components) => {
    let currentProp = componentName;
    let subProp;
    if(componentName.split('.').length) {
        currentProp = componentName.split('.')[0];
        subProp = componentName.split('.')[1];
    }

    let jsonString = JSON.stringify(components[currentProp])

    let data = jsonString.replace(/"###(.*?)###"/g, (org, catched) => {
        let subData = this.getData(catched);
        return JSON.stringify(subData);
    })

    let parsedData = JSON.parse(data);
    return subProp ? parsedData[subProp] : parsedData;
}

const getFilesByExtension = (startPath, filter, allFiles = {}) =>{
    if (!fs.existsSync(startPath)){
        return;
    }

    let files = fs.readdirSync(startPath);
    for(let i=0; i < files.length; i++){
        let filename=path.join(startPath, files[i]);
        let stat = fs.lstatSync(filename);
        if (stat.isDirectory()){
            getFilesByExtension(filename, filter, allFiles);
        }
        else if (filename.endsWith(filter)) {
            let normalizedFile = path.posix.normalize(filename);
            let name = normalizedFile.split(path.sep).pop().split('.')[0];

            if(filter === '.json') {
                allFiles[name] = require(normalizedFile);
            } else {
                allFiles[name] = normalizedFile;
            }

        }
    }

    return allFiles;
}

const purgeCache = (moduleName) => {
    Object.keys(require.cache).forEach(function(key) {

        delete require.cache[key];

    });
}

class Log {
    static info(message) {
        console.info(message);
    }
    static error(message) {
        console.error(message);
    }
}

module.exports = {
    getData,
    purgeCache,
    getFilesByExtension,
    Log
}
<commit_msg>Fix getData with subdata in json<commit_after>/* eslint-disable no-undef, no-unused-vars */

const fs = require('fs');
const path = require('path');

const config = require('../config')();

const rootFolder = process.cwd();
const componentPath = path.join(config.appFolder, config.componentsFolder);

const getAllJsonFiles = () => {
    const componentsFolder = path.join(
        process.cwd(),
        config.appFolder,
        config.componentsFolder
    )
    const containersFolder = path.join(
        process.cwd(),
        config.appFolder,
        config.containersFolder
    )

    const jsonFiles = {
        ...getFilesByExtension(componentsFolder, '.json'),
        ...getFilesByExtension(containersFolder, '.json')
    };

    return jsonFiles;
}

const getData = (componentName, components = null) => {
    components = components || getAllJsonFiles();

    let currentProp = componentName;
    let subProp;
    if(componentName.split('.').length) {
        currentProp = componentName.split('.')[0];
        subProp = componentName.split('.')[1];
    }

    let jsonString = JSON.stringify(components[currentProp])

    let data = jsonString.replace(/"###(.*?)###"/g, (org, catched) => {
        let subData = getData(catched);
        return JSON.stringify(subData);
    })

    let parsedData = JSON.parse(data);
    return subProp ? parsedData[subProp] : parsedData;
}

const getFilesByExtension = (startPath, filter, allFiles = {}) =>{
    if (!fs.existsSync(startPath)){
        return;
    }

    let files = fs.readdirSync(startPath);
    for(let i=0; i < files.length; i++){
        let filename=path.join(startPath, files[i]);
        let stat = fs.lstatSync(filename);
        if (stat.isDirectory()){
            getFilesByExtension(filename, filter, allFiles);
        }
        else if (filename.endsWith(filter)) {
            let normalizedFile = path.posix.normalize(filename);
            let name = normalizedFile.split(path.sep).pop().split('.')[0];

            if(filter === '.json') {
                allFiles[name] = require(normalizedFile);
            } else {
                allFiles[name] = normalizedFile;
            }

        }
    }

    return allFiles;
}

const purgeCache = (moduleName) => {
    Object.keys(require.cache).forEach(function(key) {

        delete require.cache[key];

    });
}

class Log {
    static info(message) {
        console.info(message);
    }
    static error(message) {
        console.error(message);
    }
}

module.exports = {
    getData,
    purgeCache,
    getFilesByExtension,
    Log
}
<|endoftext|>


<commit_before>var querystring = require('querystring');
var OAuth = require('oauth').OAuth;

var Client = function(oauth_config) {
  this.oauthToken = oauth_config.token;
  this.oauthTokenSecret = oauth_config.token_secret;

  this.oauth = new OAuth(
    null,
    null,
    oauth_config.consumer_key,
    oauth_config.consumer_secret,
    oauth_config.version || "1.0",
    null,
    'HMAC-SHA1'
  );

  return this;
};

var base_url = "http://api.yelp.com/v2/";

Client.prototype.get = function(resource, params, callback) {
  return this.oauth.get(
    base_url + resource + '?' + querystring.stringify(params),
    this.oauthToken,
    this.oauthTokenSecret,
    function(error, data, response) {
      if(!error) data = JSON.parse(data);
      callback(error, data, response);
    }
  );
}

/*
Exampe:
yelp.search({term: "food", location: "Montreal"}, function(error, data) {});
*/
Client.prototype.search = function(params, callback) {
  return this.get('search', params, callback);
}

/*
Example:
yelp.business("yelp-san-francisco", function(error, data) {});
*/
Client.prototype.business = function(id, callback) {
  return this.get('business/' + id, null, callback);
}

/*
Exampe:
yelp.phone_search({phone: "+12223334444"}, function(error, data) {});
*/
Client.prototype.phone_search = function(params, callback) {
  return this.get('phone_search', params, callback);
}

// @see http://www.yelp.com/developers/documentation/v2/authentication
module.exports.createClient = function(oauth_config) {
  return new Client(oauth_config);
};
<commit_msg>Added latitude and longitude<commit_after>var querystring = require('querystring');
var OAuth = require('oauth').OAuth;

var Client = function(oauth_config) {
  this.oauthToken = oauth_config.token;
  this.oauthTokenSecret = oauth_config.token_secret;

  this.oauth = new OAuth(
    null,
    null,
    oauth_config.consumer_key,
    oauth_config.consumer_secret,
    oauth_config.version || "1.0",
    null,
    'HMAC-SHA1'
  );

  return this;
};

var base_url = "http://api.yelp.com/v2/";

Client.prototype.get = function(resource, params, callback) {
  var query_url;
  /*
  If searching with term and ll (latitude and longitude)
  Example:
  yelp.search({term: "restaurants", ll: ['41.891519', '-87.638257']}, function(error, data) {
    console.log(error);
    console.log(data);
  });
  */
  if(params.ll && params.term && resource === 'search'){
    query_url = base_url + resource + '?term=' + params.term + '&ll=' + params.ll[0] + ',' + params.ll[1]
  }
  else {
    query_url = base_url + resource + '?' + querystring.stringify(params)
  }
  return this.oauth.get(
    query_url,
    this.oauthToken,
    this.oauthTokenSecret,
    function(error, data, response) {
      if(!error) data = JSON.parse(data);
      callback(error, data, response);
    }
  );
}

/*
Exampe:
yelp.search({term: "food", location: "Montreal"}, function(error, data) {});
*/
Client.prototype.search = function(params, callback) {
  return this.get('search', params, callback);
}

/*
Example:
yelp.business("yelp-san-francisco", function(error, data) {});
*/
Client.prototype.business = function(id, callback) {
  return this.get('business/' + id, null, callback);
}

/*
Exampe:
yelp.phone_search({phone: "+12223334444"}, function(error, data) {});
*/
Client.prototype.phone_search = function(params, callback) {
  return this.get('phone_search', params, callback);
}

// @see http://www.yelp.com/developers/documentation/v2/authentication
module.exports.createClient = function(oauth_config) {
  return new Client(oauth_config);
};
<|endoftext|>