Skip to content

Instantly share code, notes, and snippets.

@infloop
Last active October 19, 2015 10:43
Show Gist options
  • Save infloop/1e96e0819a15d70ad574 to your computer and use it in GitHub Desktop.
Save infloop/1e96e0819a15d70ad574 to your computer and use it in GitHub Desktop.
marionette.app.utils
(function (app , _, model, $) {
/**
* @extends {Backbone.Collection}
* @type {app.collections.collectionAbstract}
*/
app.collections.collectionAbstract = Backbone.Collection.extend({
modelName: 'abstractModel',
model: model,
urlType: '',
urlParam: '',
setUrlType: function (type) {
this.urlType = type;
},
setUrlParam: function (param) {
this.urlParam = param;
},
url: function () {
switch (this.urlType) {
case "getByUser":
return '/api/' + this.modelName + '/'+app.globalUrlExt +'/getListByUser/' + this.urlParam;
break;
//case "destroy":
// return '/api/' + this.modelName + '/' + this.urlParam;
// break;
default:
return app.globalUrlBase + this.modelName;
if (this.isNew()) {
return app.globalUrlBase + this.modelName;
} else {
return app.globalUrlBase + this.modelName + '/' + this.get("id");
}
break;
}
},
execute: function(actionName, data, options) {
$.ajax({
method: "POST",
url: '/api/' + this.modelName + '/exec/'+actionName+'/',
contentType: 'application/json',
data: JSON.stringify(data),
success: options.success,
error: options.error
})
},
fetch: function(options) {
//TODO - review
var _this = this;
var success = (function() {});
var error = (function() {});
this.trigger("fetch:before");
options = options || {};
if(_.isFunction(options.success)) {
success = options.success;
}
options.success = function(models, responce) {
_this.trigger("fetch:after");
//console.log("after");
success(models, responce);
};
if(_.isFunction(options.error)) {
error = options.error;
}
options.error = function(models, responce) {
_this.trigger("fetch:after");
//console.log("after err");
error(models, responce);
};
return Backbone.Collection.prototype.fetch.call(this, options);
},
destroy: function(ids) {
var models = [];
if(!ids) {
this.each(function(model) {
models.push(model);
});
} else {
_.each(ids, function(id) {
models.push(this.collection.at(id));
},this);
}
_.invoke(models, 'destroy');
}
});
})(app, _, app.models.modelAbstract, jQuery);
(function (app , $ ,_) {
var actions = ["new", "edit"];
/**
* @extends {Backbone.Marionette.Layout}
* @type {app.forms.formAbstract}
* @constructor
*/
app.forms.formAbstract = Backbone.Marionette.Layout.extend({
template:'',
className: 'abstract-form',
strings: {
titleNew: 'New abstract item',
titleEdit: "Edit abstract item",
success: 'Saved'
},
action: 'edit', // new | edit
modelName: 'abstractModel',
model: null,
collection: null,
regions:{},
modelEvents: {
'invalid': 'onValidationError'
},
templateHelpers: function() {
return {
action: this.action,
t_titleNew: this.strings.titleNew,
t_titleEdit: this.strings.titleEdit,
t_success: this.strings.success
};
},
triggers: function() {
var e = {};
//e["click button[type='submit']"] = "submit";
// e["click button.submit"] = "submit";
e["submit"] = "submit";
e["click .cancel"] = "cancel:click";
e["focus input"] = "input:focus";
return e;
},
initialize:function(options) {
this.listenTo(this, "save:success", this.onSuccess, this);
this.listenTo(this, "save:error", this.onError, this);
this.listenTo(this, "submit:success", this.onSubmitSuccess, this);
this.listenTo(this, "before:submit", this.onBeforeSubmit, this);
if(options.action) {
if(actions.indexOf(options.action)>=0) {
this.action = options.action;
} else
throw new Error("unsupported form action ["+options.action.toString()+"]");
}
},
//events
onRender:function() {
if (this.model) {
app.utils.arrayToFormData(this.model.toJSON(), this.$el, app.utils.capitaliseFirstLetter(this.modelName));
}
this.$el.find("img").each(function() {
var fileId = $(this).data("file");
var _this = this;
if(fileId) {
$.ajax({
url:"/api/file/"+fileId,
type: "GET",
success: function(file) {
$(_this).attr("src",file.url);
}
});
}
});
},
onSubmit:function(ev) {
this.submit();
return false;
},
onInputFocus: function() {
this.clearErrors();
},
onSuccess: function() {
},
onSubmitSuccess: function(attributes) {
},
onBeforeSubmit: function(model) {
},
onError: function(model, response) {
console.log(response);
if(!response) {
this.$el.find('.main-error-block').html("something went wrong").show();
return;
}
if(!response.responseJSON) {
this.$el.find('.main-error-block').html(response.responseText).show();
return;
}
this.onValidationError(this.model, response.responseJSON);
},
//methods
submit: function(customAttributes, ignoreForm, ignoreModel){
var _this = this;
var attributes = (customAttributes || {});
if(!ignoreForm) {//Если ignoreForm == true то не парсим DOM формы
$.extend(true,attributes,app.utils.formDataToArray(this.$el.find('form')));
}
//TODO why it is not in the end
this.trigger("submit:success", attributes);
if(!ignoreModel) {
if(!this.model) {
this.model = new app.models[this.modelName](attributes);
//for modelEvents support
Marionette.bindEntityEvents(this, this.model, Marionette.getOption(this, "modelEvents"));
} else if(!ignoreModel) {
this.model.set(attributes);
}
//TODO why here is !
if(!this.model.id)
this.model.id = null;
this.trigger("before:submit", this.model);
this.model.save(null, { validate: true,
success:function(model,response){
_this.trigger("save:success", model, response);
},
error: function(err, response){
_this.trigger("save:error", err, response);
}
});
}
},
hide: function(){
$(this.$el).hide();
},
show: function(){
$(this.$el).show();
},
clear: function(){
this.clearErrors();
$(this.$el).children()[0].reset();
},
clearErrors: function() {
this.$el.find('.form-group').removeClass('has-error');
this.$el.find('span.glyphicon.glyphicon-remove').addClass('glyphicon-ok').hide();
this.$el.find('span.error-block').html('').hide();
this.$el.find('span.main-error-block').html('').hide();
},
onValidationError: function (model, errors) {
_.each(_.keys(errors), function (key) {
this.$el.find('input[name="' + key + '"]').closest('.form-group').removeClass('has-success').addClass('has-error');
this.$el.find('input[name="' + key + '"]').closest('.form-group').find('span.glyphicon').removeClass('glyphicon-ok').addClass('glyphicon-remove').show();
this.$el.find('input[name="' + key + '"]').closest('.form-group').find('span.error-block').html(errors[key]).show();
}, this);
},
attachFileUploader: function(element, options){
if(!(element instanceof $)) {
throw new Error("attachFileUploader - not a jquery element");
}
var modelName = options.modelName || "";
var _this = this;
return element.fileupload({
url: "/api/upload/" + modelName,
dataType: 'json',
formData: (options.data || {}),
sequentialUploads: true,
done: function(e, data) {
$(this).closest(".fileinput-button").find("span").html("Uploaded");
if(options.done)
options.done.call(_this,data.result);
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$(this).closest(".fileinput-button").find("span").html("Uploading..."+progress+" %");
},
add: function (e, data) {
var jqXHR = data.submit();
},
change: function (e, data) {
$(this).closest(".fileinput-button").find("span").html("Loading...");
}
});
}
});
})(app, $, _);
(function (app, collection, model) {
/**
* @extends {Backbone.Marionette.ItemView}
* @type {app.views.itemViewAbstract}
*/
app.views.itemViewAbstract = Backbone.Marionette.ItemView.extend({
template:'',
className: 'abstract-item-view',
strings: {
title: 'Abstract item'
},
modelName: 'abstractModel',
model: null,
initialize: function() {
Marionette.bindEntityEvents(this, this.model, Marionette.getOption(this, "modelEvents"));
},
modelEvents: {
"change":"render"
},
confirmDelete: function(text){
var _this = this;
var confirm = new app.forms.confirmationForm({
ok: function(cb) { _this.model.destroy(); cb(); },
text: 'Delete [<nobr>' + text + '</nobr>] ?'
});
app.mt.window.show(confirm);
}
});
})(app, app.collections.collectionAbstract, app.models.modelAbstract);
(function (app, _) {
_.extend(Backbone.Model.prototype, Backbone.Validation.mixin);
/**
* @extends {Backbone.Validation}
* @extends {Backbone.Model}
* @type {app.models.modelAbstract}
*/
app.models.modelAbstract = Backbone.Model.extend({
modelName: 'abstractModel',
defaults: function () {
return {};
},
validation: {},
urlType: "",
urlParam: "",
setUrlType: function(type){
this.urlType = type;
},
setUrlParam: function (param) {
this.urlParam = param;
},
url: function () {
switch (this.urlType){
case "exec":
return app.globalUrlBase + this.modelName + "/exec/" + this.urlParam + "/";
break;
default:
if (this.isNew()){
return app.globalUrlBase + this.modelName;
} else {
return app.globalUrlBase + this.modelName + '/' + this.get("id");
}
break;
}
},
initialize: function () {
},
execute: function(method, options) {
if(_.isFunction(options)) {
var cb = options;
options.success = function(result) {
cb(null, result);
};
options.error = function(err) {
cb(err);
}
}
var oldUrlType = this.urlType;
var oldUrlParam = this.urlParam;
this.urlType = 'exec';
this.urlParam = method;
this.save(null, options);
this.urlType = oldUrlType;
this.urlParam = oldUrlParam;
}
});
})(app, _);
((function (root,_) {
/*_.templateSettings = {
interpolate: /\{\{=(.+?)\}\}/g,
evaluate: /\{\{(.+?)\}\}/g
};*/
/**
* Application
* @type {{utils: {}, mt: Marionette.Application, collectionCache: {}, templateCache: {}, router: {}, forms: {}, views: {}, models: {}, collections: {}, globalUrlBase: string, globalUrlExt: string, clientProcess: Function}}
*/
root.app = {
//different utility functions
utils:{},
mt:new Backbone.Marionette.Application(),
//caches
collectionCache: {},
templateCache: {},
//router
router: {},
//classes
forms: {},
views: {},
models: {},
collections: {},
globalUrlBase: "/api/",
globalUrlExt: "ext",
clientProcess: (function(cProcess, context, cTimeout, doNotStart, cComplete) {
this.maxCount = 1000;
this.count = 0;
this.context = context;
this.cProcess = cProcess;
this.cComplete = cComplete;
this.cTimeout = (cTimeout | 0) || 100;
this.working = 1;
this.toStop = false;
this.start = function() {
this.toStop = false;
this.working = 2;
this.d = _.bind(this.done,this);
this.c = _.bind(this.complete,this);
this.f = _.bind(function() {
if(this.toStop) {
clearTimeout(this.cId);
return;
}
clearTimeout(this.cId);
this.cId = setTimeout(this.f, this.cTimeout);
if(this.working == 2) {
this.count++;
if( this.count>= this.maxCount)
this.stop();
return;
}
this.cProcess.call(this.context, this.d, this.c);
this.working = 2;
},this);
this.cProcess.call(this.context, this.d);
this.cId = setTimeout(this.f, this.cTimeout);
};
this.done = function(stop) {
this.working = 1;
if(stop)
this.stop();
};
this.complete = function() {
this.cComplete();
this.stop();
};
this.stop = function() {
this.toStop = true;
};
this.cId = 0;
if(!doNotStart)
this.start();
})
};
})(window,_));
(function (app, model) {
/**
* @extends {app.forms.formAbstract}
* @type {app.forms.confirmationForm}
*/
app.forms.confirmationForm = app.forms.formAbstract.extend({
className: "confirmation-form",
formName: 'confirmationForm',
template: '#confirmationForm',
modelName: 'confirmation',
actionOk: null,
actionCancel: null,
text: '',
error: '',
triggers: function () {
var e = {};
e["click button[data-action='ok']"] = "ok:click";
e["click button[data-action='cancel']"] = "cancel:click";
return e;
},
templateHelpers: function() {
return {
text: this.text,
error: this.error
};
},
initialize: function (options) {
options = options || {};
this.actionOk = options.ok || (function(cb) { cb = (cb|| (function(){})); cb(); });
this.actionCancel = options.cancel || (function(cb) { cb = (cb|| (function(){})); cb(); });
this.text = options.text || '';
this.error = '';
this.render();
//app.forms.formAbstract.prototype.initialize.call(this, options);
},
onRender: function () {
//app.forms.formAbstract.prototype.onRender.call(this);
},
onClose: function (e) {
},
onOkClick: function (model) {
var _this = this;
this.actionOk(function(err, res) {
if(!err) {
app.mt.window.close();
} else {
_this.error = err;
_this.render();
}
});
},
onCancelClick: function(model) {
var _this = this;
this.actionCancel(function(err, res) {
if(!err) {
app.mt.window.close();
} else {
_this.error = err;
_this.render();
}
});
},
onError: function (model, responce) {
app.forms.formAbstract.prototype.onError().call(this, model, responce);
}
});
})(app, app.models.confirmation);
/**
* Simple module with helper util functions
*
* Created: 21.10.2013
* Author: Kirill Minenko
*/
(function (utils) {
/**
* Выводит событие
*
* @param event
*/
utils.logEvent = function (event) {
console.log("["+event+"]",arguments);
};
/**
* Удаляет из строки все html-сущности
* @param string
* @returns {*}
*/
utils.stripHtml = function (string) {
return string.replace(/<(?:.|\n)*?>/gm, '');
};
/**
* Делает первую букву строки заглавной
* @param string
* @returns {string}
*/
utils.capitaliseFirstLetter = function (string) {
if(!string) return;
return string.charAt(0).toUpperCase() + string.slice(1);
};
/**
* Собирает все данные из элементов input,checkbox,radio,select формы и возвращяет объект
* @param form form class or form element
* @returns {{}}
*/
utils.formDataToArray = function (form) {
if (!form) {
throw new Error("Form class or form element is undefined");
}
var formElement = null;
//var formClass may be class name or jquery object
if (typeof form === 'string') {
formElement = $('.' + form);
} else {
formElement = form;
}
var inputs = formElement.find("input[type!='checkbox'],textarea");
var dataPrepared = {};
inputs.each(function () {
var elementName = $(this).attr('name');
if (elementName != '') {
dataPrepared[elementName] = this.value;
}
});
var selectSet = formElement.find("select");
selectSet.each(function () {
var selectName = $(this).attr('name');
dataPrepared[selectName] = this.value;
});
var checkboxSet = formElement.find("input[type='checkbox']");
checkboxSet.each(function () {
var checkboxName = $(this).attr('name');
dataPrepared[checkboxName] = (this.checked) ? 1 : 0;
});
var radioSet = formElement.find("input[type='radio']");
radioSet.each(function () {
var radioName = $(this).attr('name');
if (this.checked)
dataPrepared[radioName] = this.value;
});
return dataPrepared;
};
/**
* Раскидывает модель данных по форме
*
* @param arrayData data array
* @param form form class or form element
* @param entityName
* @returns {boolean}
*/
utils.arrayToFormData = function (arrayData, form, entityName) {
var formElement = null;
//var formClass may be class name or jquery object
if (typeof form === 'string') {
formElement = $('.' + form);
} else {
formElement = form;
}
if (!formElement) {
throw new Error("Form class or form element is undefined");
}
//var formClass may be class name or jquery object
var inputs = formElement.find('input,textarea,select');
inputs.each(function () {
var inputName = this.name;
if ((!_.isUndefined(arrayData[inputName]) && !_.isNull(arrayData[inputName])) && this.type != 'checkbox' && this.type != 'radio') {
$(this).val(arrayData[inputName]);
}
});
var checkboxSet = formElement.find("input[type='checkbox']");
checkboxSet.each(function () {
var checkboxName = this.name;
if (arrayData[checkboxName] !== undefined) {
if (arrayData[checkboxName]+'' == this.value) {
$(this).attr('checked', true);
}
}
});
var radioListSet = formElement.find("input[type='radio']");
radioListSet.each(function () {
var radioName = this.name;
if (arrayData[radioName] !== undefined) {
if (arrayData[radioName]+'' == this.value) {
$(this).attr('checked', true);
}
}
});
return true;
};
utils.unixTimestampToDate = function(unixTimestamp) {
return new Date(unixTimestamp*1000);
};
utils.unixTimestampToDateString = function(unixTimestamp) {
if(!unixTimestamp || unixTimestamp=='null') return '';
var date = new Date(unixTimestamp*1000);
return utils.getDateString(date);
};
utils.stringToDate = function(string) {
var year = Number(string.split("-")[0]);
var month = Number(string.split("-")[1]);
var day = (string.split("-")[2]).split(" ")[0];
var hour = ((string.split("-")[2]).split(" ")[1]).split(":")[0];
var minutes = ((string.split("-")[2]).split(" ")[1]).split(":")[1];
var seconds = ((string.split("-")[2]).split(" ")[1]).split(":")[2];
return new Date(year, month, day, hour, minutes, seconds);
};
utils.getDatePoint = function(date) {
var day = (date.getDate()<10) ? '0' + date.getDate() : date.getDate();
var month = (date.getMonth()<10) ? '0' + date.getMonth() : date.getMonth();
return day + '.' + month + '.' + date.getFullYear();
};
utils.getDateString = function(date) {
//var month = ["январь", "февраль", "март", "апрель", "май", "июнь", "июль","август", "сентябрь", "октябрь", "ноябрь", "декабрь"];
var month = ["января", "февраля", "марта", "апреля", "мая", "июня", "июля","августа", "сентября", "октября", "ноября", "декабря"];
var day = (date.getDate()<10) ? '0' + date.getDate() : date.getDate();
return day + ' ' + month[date.getMonth()] + ' ' + date.getFullYear();
};
utils.stringSearch = function(needle,string,caseSensitive) {
//if(_.isString(string)) {
needle = needle+'';
string = string+'';
if(!caseSensitive) {
needle = needle.toUpperCase();
string = string.toUpperCase();
}
if (string.indexOf(needle)>=0) {
return true;
}
return false;
};
/**
* Проверяет, есть ли в массиве haystack значение needle
*
* TODO Зачем эта функция, если есть array.indexOf()
*
* @param needle
* @param haystack
* @param strict
* @returns {boolean}
*/
utils.inArray = function(needle, haystack, strict) {
var found = false, key, strict = !!strict;
for (key in haystack) {
if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
found = true;
break;
}
}
return found;
};
utils.centerByHeight = function(el) {
$(el).css({
'position' : 'absolute',
'left' : '50%',
'top' : '50%',
'margin-left' : -$(this).width()/2,
'margin-top' : -$(this).height()/2
});
};
utils.removeNonVisibleChars = function(str) {
if(!_.isString(str)) { return false; }
return str.replace(/[\r\n]/g,"");
};
utils.trim = function(str) {
str = str.replace( /^\s*/,'');
str = str.replace( /\s*$/, '' );
return str;
};
utils.splitByWords = function(str) {
if(!_.isString(str)) { return false; }
str = utils.trim(str);
return str.split(/[\s\n,]+/g);
};
utils.insertAtCaretAny = function(text) {
var sel, range, html;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
range.insertNode( document.createTextNode(text) );
}
} else if (document.selection && document.selection.createRange) {
document.selection.createRange().text = text;
}
};
utils.insertAtCaret = function(textarea, text) {
var txtarea = textarea;
var scrollPos = txtarea.scrollTop;
var strPos = 0;
var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ?
"ff" : (document.selection ? "ie" : false ) );
if (br == "ie") {
txtarea.focus();
var range = document.selection.createRange();
range.moveStart ('character', -txtarea.value.length);
strPos = range.text.length;
}
else if (br == "ff") strPos = txtarea.selectionStart;
var front = (txtarea.value).substring(0,strPos);
var back = (txtarea.value).substring(strPos,txtarea.value.length);
txtarea.value=front+text+back;
strPos = strPos + text.length;
if (br == "ie") {
txtarea.focus();
var range = document.selection.createRange();
range.moveStart ('character', -txtarea.value.length);
range.moveStart ('character', strPos);
range.moveEnd ('character', 0);
range.select();
}
else if (br == "ff") {
txtarea.selectionStart = strPos;
txtarea.selectionEnd = strPos;
txtarea.focus();
}
txtarea.scrollTop = scrollPos;
};
utils.getInputSelection = function(el) {
var start = 0, end = 0, normalizedValue, range,
textInputRange, len, endRange;
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
start = el.selectionStart;
end = el.selectionEnd;
} else {
range = document.selection.createRange();
if (range && range.parentElement() == el) {
len = el.value.length;
normalizedValue = el.value.replace(/\r\n/g, "\n");
// Create a working TextRange that lives only in the input
textInputRange = el.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
// Check if the start and end of the selection are at the very end
// of the input, since moveStart/moveEnd doesn't return what we want
// in those cases
endRange = el.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
start = end = len;
} else {
start = -textInputRange.moveStart("character", -len);
start += normalizedValue.slice(0, start).split("\n").length - 1;
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
end = len;
} else {
end = -textInputRange.moveEnd("character", -len);
end += normalizedValue.slice(0, end).split("\n").length - 1;
}
}
}
}
return {
start: start,
end: end
};
};
utils.offsetToRangeCharacterMove = function(el, offset) {
return offset - (el.value.slice(0, offset).split("\r\n").length - 1);
};
utils.setInputSelection = function(el, startOffset, endOffset) {
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
el.selectionStart = startOffset;
el.selectionEnd = endOffset;
} else {
var range = el.createTextRange();
var startCharMove = offsetToRangeCharacterMove(el, startOffset);
range.collapse(true);
if (startOffset == endOffset) {
range.move("character", startCharMove);
} else {
range.moveEnd("character", offsetToRangeCharacterMove(el, endOffset));
range.moveStart("character", startCharMove);
}
range.select();
}
};
utils.getOwnerType = function(ownerType) {
var type;
if(ownerType == 'user'){
type = 'profile';
} else {
type = ownerType;
}
return type;
};
utils.getUrlWithoutHash = function() {
var href = window.location.href;
var position = href.indexOf('#')
if(position != -1) {
href = href.substring(0, position);
}
if(href[href.length-1] == '/')
{
href = href.substring(0, href.length-1);
}
return href.replace(location.protocol+"//"+location.host, '');
};
utils.getCurrentUrl = function() {
var href = window.location.href;
return href.replace(location.protocol+"//"+location.host, '');
};
utils.getCurrentType = function() {
var href = window.location.href;
href = href.replace(location.protocol+"//"+location.host, '')
href = href.substring(1, href.length);
var position = href.indexOf('/');
if(position != -1) {
href = href.substring(0, position);
}
return href;
};
utils.getOwnerByPrefix = function(title) {
if(title == 'dep')
{
return 'depProfile';
} else
if(title == 'org')
{
return 'organization';
} else
{
return title;
}
};
utils.getFiltersFromQuery = function(query) {
var filters = [];
var pairs = (query+'').split("&");
_.each(pairs, function(pair) {
var filter = pair.split(":", 2);
if(filter.length != 2)
return;
filter[0] = 'getListBy'+ utils.capitaliseFirstLetter(filter[0]);
filters.push(filter);
});
return (filters.length > 0) ? filters : false;
};
utils.base64 = {
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for encoding
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = utils.base64._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
}
return output;
},
// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = utils.base64._utf8_decode(output);
return output;
},
// private method for UTF-8 encoding
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}
})(app.utils);
//useful
window.requestAnimFrame = (function(){
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function */ callback){
window.setTimeout(callback, 1000 / 60);
}
)
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment