//==========================================================
//
// ___ ___ ___ ___ ___ ___ ___ ___ ___
// /\__\ /\ \ /\__\ /\ \ /\__\ /\ \ /\ \ /\__\ /\ \
// /:/ / /::\ \ /::| | /::\ \ /:/ _/_ /::\ \ /::\ \ /:/ / /::\ \
// /:/__/ /:/\:\ \ /:|:| | /:/\:\ \ /:/ /\__\ /:/\:\ \ /:/\:\ \ /:/__/ /:/\ \ \
// /::\ \ ___ /:/ \:\ \ /:/|:|__|__ /::\~\:\ \ /:/ /:/ _/_ /:/ \:\ \ /::\~\:\ \ /::\__\____ _\:\~\ \ \
// /:/\:\ /\__\ /:/__/ \:\__\ /:/ |::::\__\ /:/\:\ \:\__\ /:/_/:/ /\__\ /:/__/ \:\__\ /:/\:\ \:\__\ /:/\:::::\__\ /\ \:\ \ \__\
// \/__\:\/:/ / \:\ \ /:/ / \/__/~~/:/ / \:\~\:\ \/__/ \:\/:/ /:/ / \:\ \ /:/ / \/_|::\/:/ / \/_|:|~~|~ \:\ \:\ \/__/
// \::/ / \:\ /:/ / /:/ / \:\ \:\__\ \::/_/:/ / \:\ /:/ / |:|::/ / |:| | \:\ \:\__\
// /:/ / \:\/:/ / /:/ / \:\ \/__/ \:\/:/ / \:\/:/ / |:|\/__/ |:| | \:\/:/ /
// /:/ / \::/ / /:/ / \:\__\ \::/ / \::/ / |:| | |:| | \::/ /
// \/__/ \/__/ \/__/ \/__/ \/__/ \/__/ \|__| \|__| \/__/
//
//
//
// @ HOMEWORKS FRAMEWORK
// @ All Rights Reserved IGAWorks Inc.
//
//==========================================================
//
// @ UPDATE 2017-01-13
// @ AUTHOR Kenneth
//
//=========================================================
window.HOMEWORKS_VERSION = '2.0.9.4';
var VERSION = '@@VERSION';
if (VERSION.replace(/@/g, '') !== 'VERSION') {
window.HOMEWORKS_VERSION = VERSION;
}
var _promiseVariables = {}; // Promise standard global variables.
var _superVariables = {}; // Plugin option standard global variables.
/*=================================================
*= NOTE - String formatter.
*= DATE - 2016-01-19
*================================================*/
String.prototype.getFormat = function (options) {
var string = this;
for (var idx in options) {
var value = options[idx];
idx = idx.replace(/\\/gi, '\\\\')
.replace(/-/gi, '\\-');
var regexp = new RegExp("{" + idx + "}", "gi");
string = string.replace(regexp, value);
}
return string.toString();
};
/*=================================================
*= NOTE - Component biding feature.
*= DATE - 2016-01-19
*================================================*/
Function.prototype.hook = function (name, args) {
var context = this;
try {
jQuery(document).ready(function() {
var format = '[data-{data-name}]';
jQuery(format.getFormat({
'data-name': name
})).each(function () {
var element = $(this);
var target = element.data('pen');
var plugin = element.data(name);
if (plugin === false)
return true;
if (typeof context === 'function') {
if (typeof target === 'undefined') {
context.call(element, null, plugin, args);
} else {
context.call(element, $(target), plugin, args);
}
}
});
});
} catch (e) {
console.trace(e.stack);
}
};
/*=================================================
*= NOTE - HOMEWORKS Component define region.
*= DATE - 2016-01-19
*================================================*/
/**
* @constructor
* @description HOMEWORKS COMPONENT Store constructor, It is separated by each COMPOENTS.
* @see Refer an example document {@link https://kennethanceyer.gitbooks.io/homeworks-framework-wiki/content/DEVELOPMENT/ComponentData.html|here}.
* @author Kenneth <kenneth@igaworks.com>
* @param {ComponentMethod} context - HOMEWORKS ComponentMethod Context.
* @param {string} id - HOMEWORKS Component Unique ID
* @returns {ComponentData}
*/
function ComponentData(context, id) {
/*=================================================
*= NOTE - HOMEWORKS Compoent storagy variables region.
*= DATE - 2016-01-19
*================================================*/
if (typeof _superVariables[id] === 'undefined') {
_superVariables[id] = {};
}
/**
* @member
* @description ComponentData's store variable, This is the heart of ComponentData.
* @property {ComponentData} $self - Reference of ComponentData (self).
* @property {ComponentMethod} $super - Reference of ComponentMethod.
* @property {ComponentHelper} $helper - Reference of ComponentHelper.
* @property {Boolean} _init - If component already done initialize process, It will be true (This is prevent a duplication of initializing).
* @property {Boolean} _anim - The logical variable of Component animating.
* @property {Boolean} _bind - The logical variable of Component binding.
* @property {Object} anim - Animation configuration object.
* @property {String} framework - Framework full name.
* @property {String} prefix - Framework short name for using set class name prefix of Component.
* @property {String} id - An unique id of Component, It will be automatically setted in the process of ComponentMethod.
* @property {Array<jQuery>} element - Quick reference of jQuery objects that refered frequently.
* @property {Object} global - Global properties each of Components.
*/
this.store = {
$self: this,
$super: context,
$helper: new ComponentHelper(context, this.store),
_init: false,
_anim: false,
_bind: false,
_debug: true,
anim: {
time: 300,
effect: 'swing'
},
framework: 'homeworks',
prefix: 'works',
id: id,
element: {
$window: $(window),
$document: $(document)
},
global: _superVariables[id] || {}
};
}
/**
* @constructor
* @description HOMEWORKS Helper constructor, This is helping to treat DOM Elements or JS operators.
* @see Refer an example document {@link https://kennethanceyer.gitbooks.io/homeworks-framework-wiki/content/DEVELOPMENT/ComponentHelper.html|here}.
* @author Kenneth <kenneth@igaworks.com>
* @param {ComponentMethod} context - HOMEWORKS ComponentMethod Context.
* @param {ComponentData.store} data - HOMEWORKS ComponentData store for get unique id.
* @returns {ComponentHelper}
*/
function ComponentHelper(context, data) {
/*=================================================
*= NOTE - HOMEWORKS Component shared feature.
*= DATE - 2016-01-19
*================================================*/
/**
* @function
* @description Promiss is helping to make a schedule, It is similar like setTimeout.
* @param {String} name - Promiss name for control.
* @param {Function} callback - The callback when promiss is done.
* @param {Number} time - A millisecond time for promiss.
* @param {Function} invoke - The callback when invoke request be received.
* @returns {Number} setTimeout number.
*/
this.promise = function (name, callback, time, invoke) {
var self = this;
if (typeof name === 'function' && typeof callback === 'number') {
time = callback;
callback = name;
name = context.id;
}
if (typeof invoke !== 'undefined' && invoke === true) {
this.invoke(name);
}
_promiseVariables[context.framework + '.' + name] = setTimeout(function () {
try {
delete _promiseVariables[context.framework + '.' + name];
} catch (e) {
self.log(e.stack);
}
if (typeof callback === 'function') {
callback();
}
}, time);
return _promiseVariables;
};
/**
* @function
* @description This function will invoke promiss request that you created before.
* @param {String} name - Promiss name for invoke a request.
* @param {Function} callback - The callback when promiss is done.
* @param {Number} time - A millisecond time for promiss.
* @param {Function} invoke - The callback when invoke request be received.
* @returns {Boolean}
*/
this.invoke = function (name) {
if (typeof name === 'undefined') {
name = context.id;
}
if (typeof _promiseVariables[_this.framework + '.' + name] !== 'undefined') {
try {
clearTimeout(_promiseVariables[_this.framework + '.' + name]);
delete _promiseVariables[_this.framework + '.' + name];
} catch (e) {
self.log(e.stack);
}
}
return true;
};
/**
* @function
* @description The logger of HOMEWORKS Frameworks, Use this instead console.log.
* @param {String} message - String error message or Exception object.
* @param {String} code - Error code or number.
* @returns {undefined}
*/
this.log = function (message, code) {
if (context._debug === true) {
var template = message;
if (typeof message !== 'undefined' && typeof message.stack !== 'undefined') {
console.error(message.stack);
} else {
if (typeof code !== 'undefined' && code !== null) {
template = '[' + code + '] ' + template;
}
console.error(template);
}
}
};
/**
* @function
* @description This function find template that you declared on ComponentMethod's templates array, and than replace it using a key what you gave.
* @param {String} key - The template key.
* @param {Object} map - The template object.
* @returns {String}
*/
this.parseTemplate = function (key, map) {
var data = context.template[key];
if (typeof data === 'undefined') {
this.log("'" + key + "' 이름의 템플릿이 확인되지 않습니다.");
return false;
}
return data.getFormat(map);
};
/**
* @function
* @description You can get unique id for set each of component by using this function.
* @returns {String}
*/
this.getIdentifier = function () {
var id = data.id.replace(/,?\s/g, '-');
var id_arr = id.split('');
id = [id_arr[0].toUpperCase()].concat(id_arr.splice(1, id.length)).join('');
return data.framework + id;
};
/**
* @function
* @description It will attach an event to your element, Use this function instead jQuery.bind.
* @param {jQuery} element - jQuery object for attach event.
* @param {String} type - Event type name.
* @param {Function} callback - The callback function which fired when event triggered.
* @param {Boolean} initialize - If this parameter is true, The event is triggered once automatically.
* @returns {undefined}
*/
this.bind = function (element, type, callback, initialize) {
try {
var forms = type.toString().split(' ');
for (var name in forms) {
forms[name] = forms[name] + '.' + this.getIdentifier();
}
forms = forms.join(' ');
element.on(forms, function (event, value) {
if (typeof value === 'object') {
$.extend(event, value);
}
if (typeof callback === 'function') {
callback.apply(this, Array.prototype.slice.call(arguments));
}
});
if (typeof initialize !== 'undefined' && initialize === true) {
this.triggerHandler(element, type);
}
} catch (exception) {
this.log(exception);
}
};
/**
* @function
* @description Deattach event from the jQuery object, Use this function instead jQuery.unbind.
* @param {jQuery} element - jQuery object for deattach event.
* @param {String} type - Event type name.
* @returns {undefined}
*/
this.unbind = function (element, type) {
element.off(type + '.' + this.getIdentifier());
};
/**
* @function
* @description This function will trigger an event, Use this function instead jQuery.trigger.
* @param {jQuery} element - jQuery object for trigger event.
* @param {String} type - Event type name.
* @param {Any} value - Extra values for sending the binder function.
* @returns {undefined}
*/
this.trigger = function (element, type, value) {
var forms = (type.toString().split(' '))[0];
element.trigger(value === true ? forms : (forms + '.' + this.getIdentifier()), value);
};
/**
* @function
* @description This function will trigger an event "only logically", Use this function instead jQuery.triggerHandler.
* @param {jQuery} element - jQuery object for trigger event logically.
* @param {String} type - Event type name.
* @param {Any} value - Extra values for sending the binder function.
* @returns {undefined}
*/
this.triggerHandler = function (element, type, value) {
var forms = (type.toString().split(' '))[0];
element.triggerHandler(value === true? forms : (forms + '.' + this.getIdentifier()), value);
};
}
/**
* @constructor
* @description HOMEWORKS COMPONENT Create manager, This is core constructor for making HOMEWORKS COMPONENT.
* @see Refer an example document {@link https://kennethanceyer.gitbooks.io/homeworks-framework-wiki/content/DEVELOPMENT/ComponentMethod.html|here}.
* @author Kenneth <kenneth@igaworks.com>
* @param {string} name - COMPONENT Name.
* @params {Object} settings - COMPONENT Settings.
* @returns {ComponentMethod}
*/
function ComponentMethod(name, settings) {
/*=================================================
*= NOTE - HOMEWORKS Component settings region.
*= DATE - 2016-01-19
*================================================*/
var context = this;
var _componentVariables = (new ComponentData(this, name)).store;
var _globalVariables = _componentVariables.global;
if (typeof settings.options !== 'undefined' && settings.options !== null) {
$.extend(_superVariables[name], settings.options);
}
/**
* @member {Function}
* @description The constructor of Component, This function will be called when Component mapping be started.
*/
this.init = settings.init;
/**
* @member {Object<Function>}
* @description An object wrapped functions, This object is declared Component methods.
*/
this.method = {
init: this.init
};
/**
* @member {Object<String>}
* @description An object wrapped templates, This object is declared templates which use in Component.
*/
this.template = {
};
/**
* @member {Object<Any>}
* @description Options decleared by caller, You can default option in ComponentMethod.
*/
this.options = {
};
$.extend(this.method, settings.method);
$.extend(this.template, settings.template);
$.extend(this.options, settings.options);
/*=================================================
*= NOTE - HOMEWORKS ROUTE START
*= DATE - 2017-01-10
*================================================*/
/**
* @function
* @description This function is core of ComponentMethod, This is provider to collecting Component by call patterns.
* @param {string} id - Component unique id for give to internel of Component.
* @returns {jQuery}
*/
this.route = function (id) {
var self = this;
var args = [];
if (arguments.length > 1) {
$.map(Array.prototype.slice.call(arguments, 1), function (e, i) {
args.push(e);
});
}
var ElementBinder = function () {
var _localVariables = this.data;
if (typeof this === 'object') {
if (typeof _localVariables === 'undefined') {
_localVariables = {
'_id': id,
'_init': false,
'_prototype': {},
'_options': $.extend({}, context.options)
};
this.data = _localVariables;
$.extend(_localVariables._prototype, context.method);
}
}
var componentContext = $.extend(this, {
local: _localVariables,
}, _componentVariables);
if (args.length === 0 || typeof args[0] === 'object') {
// Function(obj) or Function() pattern.
if (typeof args[0] === 'object') {
// Function(obj) pattern.
$.extend(_localVariables._options, args[0]);
}
if (_localVariables._init === false) {
_localVariables._init = true;
context.init.apply(componentContext, [$(this)].concat(Array.prototype.slice.call(args)));
}
} else if (typeof args[0] === 'string') {
// Function(Method Name) pattern.
try {
if (_localVariables._init === false) {
_localVariables._init = true;
if (typeof context.method.init !== 'undefined') {
context.method.init.apply(componentContext, [$(this)].concat(Array.prototype.slice.call(args, 1)));
} else {
context.init.apply(componentContext, [$(this)].concat(Array.prototype.slice.call(args, 1)));
}
}
return context.method[args[0]].apply(componentContext, [$(this)].concat(Array.prototype.slice.call(args, 1)));
} catch (e) {
_componentVariables.$helper.log(e.stack);
}
} else {
_componentVariables.$helper.log('Compnent has been got invalid parameters.');
}
};
if (args.length > 0 && self === window) {
// Global basic function type - Function()
var _localVariables = this.data;
if (typeof this === 'object') {
if (typeof _localVariables === 'undefined') {
_localVariables = {
'_id': id,
'_init': false,
'_prototype': {},
'_options': $.extend({}, context.options)
};
this.data = _localVariables;
$.extend(_localVariables._prototype, context.method);
}
}
var componentContext = $.extend(window, {
local: _localVariables,
}, _componentVariables);
context.method.init.apply(componentContext, Array.prototype.slice.call(args));
} else {
// By element channing method type - Elem.method()
if (typeof self !== 'undefined') {
return self.each(ElementBinder);
}
}
};
/*=================================================
*= NOTE - HOMEWORKS ROUTE END
*= DATE - 2017-01-10
*================================================*/
//============================================================================
if (_componentVariables._bind === false) {
_componentVariables._bind = true;
name = name.split(',');
for (var idx in name) {
var id = $.trim(name[idx]);
/* jshint ignore:start */
/* @DATE 2017. 01. 09 */
/* @USER Kenneth */
/* @NOTE 런타임 매개변수 독립 사용을 위한 IIFE 설정. */
!(function () {
var _id = id;
var bindFunc = function () {
return context.route.apply(this, [_id].concat(Array.prototype.slice.call(arguments)));
};
$.fn[_id] = bindFunc;
window[_id] = bindFunc;
} ());
/* jshint ignore:end */
/* jshint ignore:start */
/* @DATE 2016. 02. 22 */
/* @USER Kenneth */
/* @NOTE 함수 동적반영을 위한 jshint Escape 처리. */
for (var key in this.method) {
if (typeof $.fn[key] === 'undefined') {
!(function () {
var method = key;
$.fn[method] = function () {
var _localVariables;
var element = this[0];
if (typeof element === 'object') {
_localVariables = element.data;
if (typeof _localVariables === 'undefined') {
_localVariables = {
'_id': key,
'_init': false,
'_prototype': {},
'_options': {}
};
element.data = _localVariables;
$.extend(_localVariables._prototype, context.method);
}
var componentContext = $.extend(context, {
local: _localVariables,
}, _componentVariables);
}
if (_localVariables._init === false) {
_localVariables._init = true;
if (typeof context.method.init !== 'undefined') {
context.method.init.apply(componentContext, [$(this)].concat(Array.prototype.slice.call(arg, 1)));
} else {
context.init.apply(componentContext, [$(this)].concat(Array.prototype.slice.call(arg, 1)));
}
}
return context.method[method].apply(componentContext, [this].concat(Array.prototype.slice.call(arguments)));
};
}());
}
}
/* jshint ignore:end */
}
}
}
(function($) {
/*******************************
* NOTE - Additional jquery functions
* DATE - 2017-01-09
*******************************/
if(typeof $.fn.scrollParent === 'undefined') {
$.fn.scrollParent = function() {
var overflowRegex = /(auto|scroll)/;
var position = this.css('position');
var excludeStaticParent = (position === 'absolute');
var scrollParent = this.parents().filter(function() {
var $parent = $(this);
if (excludeStaticParent === true && $parent.css('position') === 'static') {
return false;
}
var overflowState = $parent.css(['overflow', 'overflowX', 'overflowY']);
return (overflowRegex).test(overflowState.overflow + overflowState.overflowX + overflowState.overflowY);
}).eq(0);
return position === 'fixed' || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
};
}
}(jQuery));