      1
      2 /**
      3  * @fileOverview Librería para la producción de contenidos de la web
      4  * @version 1.0
      5  * @author taejin (drumtj@gmail.com)
      6  */
      7
      8 /**
      9  * @see <a href="http://jquery.com/">http://jquery.com/</a>
     10  * @name jQuery
     11  * @class
     12  * Refiere jQuery Library (http://jquery.com/) para ver los detalles completos. Esto solo documenta las funciones y clases que son añadidos por este plug-in de jQuery.
     13  */
     14
     15
     16 /**
     17  * @see <a href="http://jquery.com/">http://jquery.com/</a>
     18  * @name fn
     19  * @class
     20  * Refiere jQuery Library (http://jquery.com/) para ver los detalles completos. Esto solo documenta la función y clases que son añadidos a jQuery por este plug-in.
     21  * @memberOf jQuery
     22  */
     23
     24 (function(){
     25
     26 	if( !("jQuery" in window) ){
     27 		throw new Error("sg library is require jQuery");
     28 	}
     29
     30 	var toString = {}.toString
     31 		, slice = [].slice;
     32
     33 	var //readyCallbackList = []
     34 		initCallbackList = []
     35 		, customTagList = {}
     36 		, customAttrList = {}
     37 		, setStageFunc
     38 		, setScaleModeFunc
     39 		, progressImg;
     40
     41 	//private
     42 	var version = "1.0"
     43 		, scaleMode = "none"
     44 		, scaleX = 0
     45 		, scaleY = 0
     46 		, stageWidth = 0
     47 		, stageHeight = 0
     48 		, $stage = null
     49 		, $content = null
     50 		, $body = null
     51 		, $window = $( window );
     52
     53 	//support
     54 	if( !("forEach" in Array.prototype) ){
     55 		Array.prototype.forEach = function ( callback ){
     56 			for( var i=0; i<this.length; i++ ){
     57 				callback.call( window, this[ i ] );
     58 			}
     59 		}
     60 	}
     61
     62 	/**
     63 	 * Configura el cursor del mouse como puntero.
     64 	 * @function
     65 	 * @name pointer
     66 	 * @memberOf jQuery.fn
     67 	 * @example
     68 	 * $( element ).pointer();
     69 	 * @example
     70 	 * $( element ).pointer( false );
     71 	 * @param {boolean} bool
     72 	 * @returns Objeto de jQuery
     73 	 * @type jQuery Object
     74 	 */
     75 	jQuery.fn.pointer = function(){
     76 		return $( this ).css( "cursor", arguments[0] == false ? "auto" : "pointer" );
     77 	};
     78
     79 	/**
     80 	 * Devuelve el valor numérico del CSS.
     81 	 * @function
     82 	 * @name cssVal
     83 	 * @memberOf jQuery.fn
     84 	 * @example
     85 	 * $( element ).cssVal( "margin-top" );
     86 	 * @param {string} cssName
     87 	 * @returns value
     88 	 * @type number
     89 	 */
     90 	jQuery.fn.cssVal = function( cssName ){
     91 		var num = parseFloat( $( this ).css( cssName ) );
     92 		return isNaN( num ) ? 0 : num;
     93 	};
     94
     95 	/**
     96 	 * Es una función que extrae las etiquetas personalizadas específicas. Extrae las etiquetas personalizadas entre los elementos hijos.
     97 	 * @function
     98 	 * @name getCustomTag
     99 	 * @memberOf jQuery.fn
    100 	 * @example
    101 	 * $( 'p' ).getCustomTag( "sg-btn-hide" );
    102 	 * @param {string} tagName
    103 	 * @returns Objeto de jQuery
    104 	 * @type jQuery Object
    105 	 * @link sg.addCustomTag referir las funciones definidas de etiquetas personalizadas.
    106 	 */
    107 	jQuery.fn.getCustomTag = function( tagName ){
    108 		var isRoot = (this == $);
    109 		for( var o in customTagList ){
    110 			if( tagName == o ){
    111 				if( isRoot ) return $( "[" + customTagList[ o ].identifier + "]" );
    112 				else return $( this ).children( "[" + customTagList[ o ].identifier + "]" );
    113 			}
    114 		}
    115 		return $;
    116 	};
    117
    118 	/**
    119 	 * Función que extrae las etiquetas personalizadas específicas.
    120 	 * @function
    121 	 * @name getCustomTag
    122 	 * @memberOf jQuery
    123 	 * @example
    124 	 * $.getCustomTag( "sg-btn-hide" );
    125 	 * @param {string} tagName
    126 	 * @returns objeto de jQuery
    127 	 * @type jQuery Object
    128 	 * @link sg.addCustomTag referir funciones definidas de etiquetas personalizadas.
    129 	 */
    130 	jQuery.getCustomTag = jQuery.fn.getCustomTag;
    131
    132
    133
    134 	function swapTag( obj, findTagName, swapTagName, identifier ) {
    135 		if ( document.querySelector( findTagName ) ) {
    136 			identifier = identifier ? ' ' + identifier + ' ' : '';
    137 			obj.html = obj.html
    138 				.replace( new RegExp( '<' + findTagName, 'g' ), '<' + swapTagName + identifier )
    139 				.replace( new RegExp( '</' + findTagName + '>', 'g' ), '</' + swapTagName + '>' );
    140 		}else{
    141 			customTagList[ findTagName ].nothing = true;
    142 		}
    143 	}
    144
    145 	function replaceTagList(){
    146 		var obj = {	html: document.body.innerHTML }
    147 			, customTagName
    148 			, customAttrName
    149 			, ctInfo, caInfo, i, j, k;
    150
    151 		for( customTagName in customTagList ){
    152 			ctInfo = customTagList[ customTagName ];
    153 			swapTag(obj, customTagName, ctInfo.originTag, ctInfo.identifier);
    154 		};
    155
    156 		//add custom attribute prefix : data-
    157 		var sgAttrNameReg = /\ssg([\-][\w]*){1,5}(\s)?=/gi,
    158 			s1 = obj.html.split('<'),
    159 			s2, matchArr, r2 = [];
    160
    161 		for ( i = 0; i < s1.length; i++ ) {
    162 			s2 = s1[ i ].split( '>' );
    163 			for ( j = 0; j < s2.length; j++ ) {
    164 				if ( j % 2 == 0 ) {
    165 					matchArr = s2[ j ].match( sgAttrNameReg );
    166 					if ( matchArr ) {
    167 						for ( k = 0; k < matchArr.length; k++ ) {
    168 							s2[ j ] = s2[ j ].replace( matchArr[ k ], " data-" + matchArr[ k ].substr( 1 ) );
    169 						}
    170 					}
    171 				}
    172 			}
    173 			r2.push( s2.join( '>' ) );
    174 		}
    175
    176 		obj.html = r2.join( '<' );
    177 		document.body.innerHTML = obj.html;
    178
    179 		delete s1;
    180 		delete s2;
    181 		delete r2;
    182 		delete obj;
    183 		delete matchArr;
    184
    185 		//support placeholder bug
    186 		$( "[placeholder]" ).each(function(i,e){
    187 			$( this ).text("").attr( "placeholder", $( this ).attr("placeholder") );
    188 		});
    189
    190 		//function apply for custom tags
    191 		var $customTag;
    192 		for( customTagName in customTagList ){
    193 			ctInfo = customTagList[ customTagName ];
    194 			if( ctInfo.nothing ) continue;
    195
    196 			$customTag = $.getCustomTag( customTagName );
    197
    198 			if( sg.isFunction( ctInfo[ "initFunc" ] ) ){
    199 				ctInfo[ "initFunc" ].call( sg );
    200 			}
    201
    202 			//execute to init function of custom attribute for each custom tag
    203 			$customTag.each(function(index, element) {
    204 				$( element ).data( "_customTagName", customTagName );
    205 				sg.setOption( element );
    206 				if( /^sg-btn-/.test( customTagName ) ) $( element ).pointer();
    207 				if( sg.isFunction( ctInfo[ "eachInitFunc" ] ) ){
    208 					ctInfo[ "eachInitFunc" ].call( element, element );
    209 				}
    210 				sg.initAttr( element );
    211 			});
    212
    213 			//execute to action function of custom attribute when called event handle
    214 			if( ctInfo[ "eventName" ] ){
    215 				$customTag.bind( ctInfo[ "eventName" ], function( e ){
    216 					var ctname = $( this ).data( "_customTagName" );
    217 					if ( !$( this ).data( "options" ).enabled ) return;
    218 					if( sg.isFunction( customTagList[ ctname ][ "eventFunc" ] ) ) customTagList[ ctname ][ "eventFunc" ].call( this, this, e );
    219 					sg.actionAttr( this );
    220 				});
    221 			};
    222 			$customTag = null;
    223 		};
    224
    225 		//apply custom attribute for all tag
    226 		for( customAttrName in customAttrList ){
    227 			caInfo = customAttrList[ customAttrName ];
    228 			if( caInfo.isForEveryTags ){
    229 				if( caInfo && sg.isFunction( caInfo[ "init" ] ) ){
    230 					$( "[data-" + customAttrName + "]" ).each(function( i, element ){
    231 						sg.setOption( element );
    232 						caInfo[ "init" ].call( element, element, element.getAttribute( "data-" + customAttrName ) );
    233 					});
    234 				}
    235 			}
    236 		}
    237 	}
    238
    239 	//call by 'resize' event
    240 	var _ww, _hh, _ch, _msc;
    241 	function applyScaleMode(){
    242 		_ww = $window.width();
    243 		_hh = $window.height();
    244 		_ch = $content.height();
    245 		_ch += $content.cssVal( "border-top-width" ) + $content.cssVal( "border-bottom-width" );
    246 		_ch += $content.cssVal( "margin-top" ) + $content.cssVal( "margin-bottom" );
    247 		_ch += $content.cssVal( "padding-top" ) + $content.cssVal( "padding-bottom" );
    248
    249 		switch( scaleMode ){
    250 			case "showall":
    251 				_msc = Math.min(_ww / stageWidth, _hh / stageHeight);
    252 				if(_ch - stageHeight <= 1){
    253 					//컨텐츠가 스테이지보다 클 때
    254 					if(_ch * _msc > _hh){
    255 						//console.log("top 0, overflow:visible");
    256 						$stage.css({
    257 							"transform" : "scale(" + _msc + ")",
    258 							"transform-origin" : "0 0",
    259 							"left" : ((_ww - stageWidth * _msc) * 0.5) + "px",
    260 							"top" : 0
    261 						});
    262
    263 						$stage.parent().css({
    264 							"overflow-y" : "visible"
    265 						});
    266 					}
    267 					//컨텐츠가 스테이지 안에 있을 때
    268 					else{
    269 						//console.log("top center, overflow:hidden");
    270 						$stage.css({
    271 							"transform" : "scale(" + _msc + ")",
    272 							"transform-origin" : "0 0",
    273 							"left" : ((_ww - stageWidth * _msc) * 0.5) + "px",
    274 							"top" : ((_hh - _ch * _msc) * 0.5) + "px"
    275 						});
    276
    277 						$stage.parent().css({
    278 							"overflow-y" : "hidden"
    279 						});
    280 					}
    281 				}
    282 				else{
    283 					//console.log("top center, overflow:auto");
    284 					$stage.css({
    285 						"transform" : "scale(" + _msc + ")",
    286 						"transform-origin" : "0 0",
    287 						"left" : ((_ww - stageWidth * _msc) * 0.5) + "px",
    288 						"top" : ((_hh - stageHeight * _msc) * 0.5) + "px"
    289 					});
    290
    291 					$stage.parent().css({
    292 						"overflow-y" : "auto"
    293 					});
    294 				}
    295 				scaleX = scaleY = _msc;
    296 			break;
    297
    298 			case "noscale":
    299 				scaleX = scaleY = 1;
    300 				$stage.css({
    301 					"transform" : "scale(" + scaleX + ")",
    302 					"transform-origin" : "0 0"
    303 				});
    304 			break;
    305
    306 			case "exactfit":
    307 				scaleX = _ww / stageWidth;
    308 				scaleY = _hh / stageHeight;
    309 				$stage.css({
    310 					"transform" : "scale(" + scaleX + ", " + scaleY + ")",
    311 					"transform-origin" : "0 0"
    312 				});
    313 			break;
    314 		}
    315 	}
    316
    317
    318 	/**
    319 	 * @namespace Librería para la producción de contenidos de la web
    320 	 * @author taejin (drumtj@gmail.com)
    321 	 * @name sg
    322 	 * @version 1.0
    323 	 * @since 2014.09.22
    324 	 * @description
    325 	 * sg library es una librería que requiere jQuery. <br>
    326 	 * Ofrece configuración de scaleMode, atributos personalizados y API para la producción de etiquetas personalizadas.<br>
    327 	 */
    328 	var sg = {
    329 		/**
    330 		 * [Read Only] es información sobre versions de la librería sg.
    331 		 * @name version
    332 		 * @memberOf sg
    333 		 * @type string
    334 		 */
    335 		get version() { return version },
    336
    337 		/**
    338 		 * [Read Only] Método de escala de stage. Se lo configura con Sg.setScaleMode y se puede colocar "showall", "exactfit" o "none" como su valor.
    339 		 * @name scaleMode
    340 		 * @memberOf sg
    341 		 * @type string
    342 		 */
    343 		get scaleMode() { return scaleMode },
    344
    345 		/**
    346 		 *[Read Only]  Es el valor del eje X de stage. Se calcula el valor cuando se ajusta scaleMode como la función de  sg.set.
    347 		 * Su proporción se calcula en base del width de stage.
    348 		 * @name scaleX
    349 		 * @memberOf sg
    350 		 * @type number 0.0 ~ 1.0
    351 		 */
    352 		get scaleX() { return scaleX },
    353
    354 		/**
    355 		 * [Read Only] stage의 Es el valor del eje Y de stage. Se calcula el valor cuando se ajusta scaleMode como la función de  sg.set.
    356 		 * Su proporción se calcula en base del width de stage.
    357 		 * @name scaleY
    358 		 * @memberOf sg
    359 		 * @type number 0.0 ~ 1.0
    360 		 */
    361 		get scaleY() { return scaleY },
    362
    363 		/**
    364 		 * [Read Only] El valor de width de stage. Se importa el valor de width de stage al configurar stage con la función de set Stage.
    365 		 * @name stageWidth
    366 		 * @memberOf sg
    367 		 * @type number
    368 		 */
    369 		get stageWidth() { return stageWidth },
    370
    371 		/**
    372 		 * [Read Only] El valor de height de stage. Se importa el valor de height de stage al configurar stage con la función de set Stage.
    373 		 * @name stageHeight
    374 		 * @memberOf sg
    375 		 * @type number
    376 		 */
    377 		get stageHeight() { return stageHeight },
    378
    379 		/**
    380 		 * [Read Only] Es un elemento configurado como stage. Se lo configura con sg.setStage.
    381 		 * @name $stage
    382 		 * @memberOf sg
    383 		 * @type jQuery Object
    384 		 */
    385 		get $stage() { return $stage },
    386
    387 		/**
    388 		 * [Read Only] Es un contenedor que contiene los elementos hijos de stage. Se crea cuando se configura $stage.
    389 		 * @name $content
    390 		 * @memberOf sg
    391 		 * @type jQuery Object
    392 		 */
    393 		get $content() { return $content },
    394
    395 		/**
    396 		 * [Read Only] $("body")
    397 		 * @name $body
    398 		 * @memberOf sg
    399 		 * @type jQuery Object
    400 		 */
    401 		get $body() { return $body },
    402
    403 		/**
    404 		 * [Read Only] $(window)
    405 		 * @name $window
    406 		 * @memberOf sg
    407 		 * @type jQuery Object
    408 		 */
    409 		get $window() { return $window },
    410
    411 		/**
    412 		 * Se puede añadir o extender funciones en sg.
    413 		 * @function
    414 		 * @name extend
    415 		 * @memberOf sg
    416 		 * @example
    417 		 * sg.extend({
    418 		 * 	myfunc: function( ){
    419 		 *		//TO DO
    420 		 * 	}
    421 		 * });
    422 		 *
    423 		 * sg.myfunc();
    424 		 * @param {object} property
    425 		 * @link sg.super Referencia
    426 		 */
    427 		extend: function( prop ){
    428 			if(typeof prop !== "object"){ throw new Error("sg.extend arguments is not Object!"); }
    429
    430 			for( var name in prop ){
    431 				//sg.hasOwnProperty( name )
    432 				if( name in sg ) prop[ name ]._super = sg[ name ];
    433 				sg[ name ] = prop[ name ];
    434 			}
    435 		},
    436
    437 		/**
    438 		 * importa la etiqueta original desde la función extendida a través de sg.extend.
    439 		 * @function
    440 		 * @name super
    441 		 * @memberOf sg
    442 		 * @example
    443 		 * sg.extend({
    444 		 * 	myfunc: function( str ){
    445 		 *		return '<<' + str + '>>';
    446 		 * 	}
    447 		 * });
    448 		 *
    449 		 * sg.myfunc( 'abc' ); //return "<<abc>>"
    450 		 *
    451 		 * sg.extend({
    452 		 * 	myfunc: function( str ){
    453 		 *		return this.super( str.toUpperCase() );
    454 		 * 	}
    455 		 * });
    456 		 *
    457 		 * sg.myfunc( 'abc' ); //return "<<ABC>>"
    458 		 * @param {object} [arguments=undefined] Parámetros de la función original.
    459 		 * @return {*} el valor devuelto de la función original.
    460 		 * @type *
    461 		 * @link sg.extend Refencia
    462 		 */
    463 		super: function(){
    464 			var _super = arguments.callee.caller._super;
    465 			return sg.isFunction( _super ) ? _super.apply( this, arguments ) : null;
    466 		}
    467 	};
    468
    469
    470 	sg.extend({
    471 		/**
    472 		 * Verificar si el objeto es función. Usar isFunction de jQuery.
    473 		 * @function
    474 		 * @name isFunction
    475 		 * @memberOf sg
    476 		 * @param {object} object
    477 		 * @returns true o false
    478 		 * @type boolean
    479 		 */
    480 		isFunction: $.isFunction,
    481
    482 		/**
    483 		 * Verificar si el objeto es array. Usar la función isArray de jQuery.
    484 		 * @function
    485 		 * @name isArray
    486 		 * @memberOf sg
    487 		 * @param {object} object
    488 		 * @returns true o false
    489 		 * @type boolean
    490 		 */
    491 		isArray: $.isArray,
    492
    493 		/**
    494 		 * Verificar si el objeto es objeto de window. Usar la función isWindow de jQuery.
    495 		 * @function
    496 		 * @name isWindow
    497 		 * @memberOf sg
    498 		 * @param {object} object
    499 		 * @returns true o false
    500 		 * @type boolean
    501 		 */
    502 		isWindow: $.isWindow,
    503
    504 		/**
    505 		 * Verificar si el objeto es número. Usar la función isNumeric de jQuery.
    506 		 * @function
    507 		 * @name isNumeric
    508 		 * @memberOf sg
    509 		 * @param {object} object
    510 		 * @returns true o false
    511 		 * @type boolean
    512 		 */
    513 		isNumeric: $.isNumeric,
    514
    515 		/**
    516 		 * Verificar si el objeto es un objeto vacío. Usar la función isEmptyObject de jQuery.
    517 		 * @function
    518 		 * @name isEmptyObject
    519 		 * @memberOf sg
    520 		 * @param {object} object
    521 		 * @returns true o false
    522 		 * @type boolean
    523 		 */
    524 		isEmptyObject: $.isEmptyObject,
    525
    526 		/**
    527 		 * Verificar si el objeto está incluido en el array. Usar la función inArray de jQuery.
    528 		 * @function
    529 		 * @name inArray
    530 		 * @memberOf sg
    531 		 * @param {object} element
    532 		 * @param {array} array
    533 		 * @param {number} index
    534 		 * @returns true o false
    535 		 * @type string
    536 		 */
    537 		inArray: $.inArray,
    538
    539 		/**
    540 		 * Devuelve data type del objeto. Usar la función type de jQuery.
    541 		 * @function
    542 		 * @name type
    543 		 * @memberOf sg
    544 		 * @param {object}
    545 		 * @returns true o false
    546 		 * @type string
    547 		 */
    548 		type: $.type
    549 	});
    550
    551
    552
    553 	sg.extend({
    554
    555 		/**
    556 		 * Añadir la función de inicialización (callback). Las funciones (callback) añadidas se ejecutan después de la inicialización.
    557 		 * @function
    558 		 * @name addInit
    559 		 * @memberOf sg
    560 		 * @example
    561 		 * sg.addInit( function(){} );
    562 		 * @param {function} callback
    563 		 */
    564 		addInit: function( callback ){
    565 			initCallbackList.push( callback );
    566 		},
    567
    568 		/**
    569 		 * Configurar la ruta de la imagen de cargando. La imagen configurada se visualiza en la pantalla durante la ejecución de página.
    570 		 * @function
    571 		 * @name setLoadingImage
    572 		 * @memberOf sg
    573 		 * @example
    574 		 * sg.setLoadingImage( '../common/img/progress.gif' );
    575 		 * @param {string} path
    576 		 */
    577 		setLoadingImage: function( path ){
    578 			progressImg = new Image();
    579 			progressImg.setAttribute("data-sg-id", "progressImg");
    580 			progressImg["onload"] = function( e ){
    581 				this.style.left = (((window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) - this.width) * 0.5) + "px";
    582 				this.style.top = (((window.innerHeight || document.documentElement.clientWidth || document.body.clientWidth) - this.height) * 0.5) + "px";
    583 				if( !sg.isReady ) document.body.appendChild( progressImg );
    584 				else delete progressImg;
    585 			};
    586 			progressImg.src = path;
    587 			progressImg.style.position = "fixed";
    588 			progressImg.style.visibility = "visible";
    589 		},
    590
    591 		/**
    592 		 * Configura stage. El stage configurado tiene acceso al sg.$stage. El stage es el criterio de controlar la escala.
    593 		 * @function
    594 		 * @name setStage
    595 		 * @memberOf sg
    596 		 * @example
    597 		 * sg.setStage( "#stage" );
    598 		 * @param {object} elementOrSelector
    599 		 */
    600 		setStage: function( elementOrSelector ){
    601 			setStageFunc = function(){
    602 				var $temp = $( elementOrSelector );
    603 				if( $temp.length == 0 ) throw new Error( "setStage : $stage is not select. (selector : " + elementOrSelector + ")" );
    604
    605 				$temp.attr( "data-sg-id", "stage" );
    606 				$content = $( "<div data-sg-id='content'></div>" );
    607 				$content.append( $temp.contents() );
    608
    609 				$temp.append( $content ).css( "position", "absolute" );
    610 				$temp.parent().css( "overflow-x", "hidden" );
    611
    612 				//border가 없으면, 때로는 크기가 잘 못 계산되기 때문에
    613 				if( $temp.cssVal( "border-top-width" ) == 0 ){
    614 					$temp.css( "border", "solid 1px rgba(255,255,255,0)" );
    615 				}
    616
    617 				stageWidth = $temp.width();
    618 				stageHeight = $temp.height();
    619
    620 				$content.css({
    621 					"min-height": stageHeight,
    622 					"visibility": "hidden"
    623 				});
    624
    625 				$stage = $temp;
    626
    627 				//apply scaleMode
    628 				if( setScaleModeFunc ){
    629 					setScaleModeFunc.apply( sg );
    630 					setScaleModeFunc = null;
    631 				}
    632 			}
    633
    634 			if( sg.isReady ){
    635 				setStageFunc.apply( sg );
    636 				setStageFunc = null;
    637 			}
    638 		},
    639
    640 		/**
    641 		 * Configura scaleMode. Se habilita siempre y cuando tenga configurado el stage, y hay modos de "showall", "exactfit" y "none".
    642 		 * @function
    643 		 * @name setScaleMode
    644 		 * @memberOf sg
    645 		 * @example
    646 		 * sg.setStage( "#stage" );
    647 		 * sg.setScaleMode( "showall" );
    648 		 * @example
    649 		 * sg.setStage( "#stage" );
    650 		 * sg.setScaleMode( "exactfit" );
    651 		 * @param {string} scaleMode
    652 		 */
    653 		setScaleMode: function( _scaleMode ){
    654 			scaleMode = _scaleMode;
    655 			setScaleModeFunc = function(){
    656 				$window.bind( "resize" , function(){
    657 					applyScaleMode();
    658 				});
    659 				applyScaleMode();
    660 			}
    661
    662 			if( $stage ){
    663 				setScaleModeFunc.apply( this );
    664 				setScaleModeFunc = null;
    665 			}
    666 		},
    667
    668 		//options setting for custom tags
    669 		/**
    670 		 * Se guarda el valor a ser aplicado al ejecutar la etiqueta personalizada en $(target).data("options").
    671 		 * @function
    672 		 * @name setOption
    673 		 * @memberOf sg
    674 		 * @example
    675 		 * sg.setOption( element );
    676 		 * @example
    677 		 * sg.setOption( element , {myClicked: false} );
    678 		 * @param {object} elementOrSelector 	- elemento o selector de jQuery
    679 		 * @param {object} [options=undefined]	- Objeto con el conjunto de valores
    680 		 */
    681 		setOption: function ( target, options ){
    682 			var op = { enabled: true };
    683 			for( var o in options ) op[ o ] = options[ o ];
    684 			$( target ).data( "options", op );
    685 		},
    686
    687 		/**
    688 		 * Añadir atributos personalizados.<br>
    689 		 * Al definir los atributos, se puede colocar true en el valor de applyAll con el fin de utlizarlos en todas las etiquetas.<br>
    690 		 * Cuando el valor es false, se habilita la función del atributo al usarlo en la etiqueta personalizada. En general,
    691 		 * los atributos personalizados definidos poseen una función especial, y esta función es habilitada con los eventos de las etiquetas personalizadas,
    692 		 * y por ende, se deja el valor básico de applyAll como false.
    693 		 * @function
    694 		 * @name addCustomAttr
    695 		 * @memberOf sg
    696 		 * @param {object} 		option 						- inicializar el objeto de atributo personalizado
    697 		 * @param {string} 		option.name 				- nombre de atributo personalizado.
    698 		 * @param {function} 	[option.init=undefined] 	- función de inicialización.
    699 		 * @param {function} 	[option.action=undefined] 	- función a ejecutar: se ejecuta cuando se procede los eventos de la etiquetas
    700 		 * personalizadas que utilitza estos atributos personalizados.
    701 		 * @param {boolean} 	[option.applyAll=true] 		- determina si se habilita la función de este atributo en todas las etiquetas básicas.
    702 		 * @example
    703 		 * //script
    704 		 * sg.addCustomAttr({
    705 		 *	name: "sg-fadeIn",
    706 		 *	init: function( element, attrValue ){
    707 		 *		$( element ).fadeIn();
    708 		 *	},
    709 		 * 	applyAll: true
    710 		 * });
    711 		 * //html
    712 		 * <div sg-fadeIn> ABCD </div>
    713 		 * @example
    714 		 * //script
    715 		 * sg.addCustomAttr({
    716 		 *	name: "sg-color",
    717 		 *	init: function( element, attrValue ){
    718 		 * 		$( element ).css( "color", attrValue );
    719 		 * 	},
    720 		 *	applyAll: true
    721 		 * });
    722 		 * //html
    723 		 * <div sg-color="red"> ABCD </div>
    724 		 * @example
    725 		 * sg.addCustomAttr({
    726 		 *	name: "sg-alert",
    727 		 *	action: function( element, attrValue ){
    728 		 * 		if( attrValue ) alert( attrValue );
    729 		 * 	}
    730 		 * });
    731 		 * @link sg.addCustomTag referir la función definida para etiquetas personalizdas.
    732 		 */
    733 		addCustomAttr: function( obj ){
    734 			customAttrList[ obj.name ] = {
    735 				init: obj.init,
    736 				action: obj.action,
    737 				isForEveryTags: obj.applyAll
    738 			}
    739 		},
    740
    741 		/**
    742 		 * Añadir etiquetas personalizadas.<br>
    743 		 * El mecanismo básico de la etiqueta personalizada es reemplazar las líneas de código html. <br>
    744 		 * Después de la carga de la página, se busca las etiquetas personalizadas en el body de html, y las reemplaza a las etiquetas básicas definidas. <br>
    745 		 * Al definir las etiquetas personalizadas, se escribe el nombre de la etiqueta original en originTag. Puede ser que las etiquetas personalizadas tengan evento o no.
    746 		 * Se puede crear una etiqueta personalizada que sirve para cambiar la estructura interna de la etiqueta definiendo una función en tagInit.
    747 		 * Por otra parte, se puede crear las etiquetas personalizadas que se habilitan con eventos específicos con una definión de función eventHandle.
    748 		 * @function
    749 		 * @name addCustomTag
    750 		 * @memberOf sg
    751 		 * @param {object} 		option 							- inicializar el objeto de etiqueta personalizado
    752 		 * @param {string}		option.name						- Nombre de etiqueta personalizada.
    753 		 * @param {string}		[option.originTag="div"]		- El nombre de la etiqueta a ser reemplazada.
    754 		 * @param {string}		[option.id="data-sg-id={name of custom tag}"]
    755 		 *														- Identificador de etiqueta personalizada. Si no es un caso específico, se usa el valor básico.
    756 		 * @param {array}		[option.attr=undefined]			- un array donde se listan los nombres de los atributos personalizados a ser usados en la etiqueta personalizada.
    757 		 * @param {function}	[option.init=undefined]			- se define las funciones si hay algo que se tiene que ejecutar al inicializar.
    758 		 * @param {function}	[option.tagInit=undefined]		- se define las funciones si hay algo que se tiene que ejecutar en cada etiqueta al inicializar.
    759 		 * @param {string}		[option.event=undefined]		- si se habilita con un evento específico, se escribe el nombre.
    760 		 * @param {function}	[option.eventHandle=undefined]	- se define la función que ejecute evento.
    761 		 * @example
    762 		 * //script
    763 		 * sg.addCustomTag({
    764 		 *	name: "sg-depth",
    765 		 * 	tagInit: function( element ){
    766 		 *		$("<p></p>").append( $( element ).contents() ).appendTo( $( element ) );
    767 		 * 	}
    768 		 * });
    769 		 * //html
    770 		 * <sg-depth> ABCD <sg-depth>
    771 		 * //result
    772 		 * <sg-depth> <p>ABCD</p> <sg-depth>
    773 		 * @example
    774 		 * //script
    775 		 * sg.addCustomTag({
    776 		 *	name: "sg-h1",
    777 		 *	attr: [ "sg-color", "sg-alert" ],
    778 		 * 	tagInit: function( element ){
    779 		 * 		$( element ).css( "font-size", "40pt" );
    780 		 * 	},
    781 		 * 	event: "click",
    782 		 * 	eventHandle: function( element ){
    783 		 * 		$( element ).animate( {"font-size": "80pt"} );
    784 		 * 	}
    785 		 * });
    786 		 * //html
    787 		 * <sg-h1 sc-color="blue" sg-alert="hello!"> ABCD </sg-h1>
    788 		 * @link jQuery.getCustomTag Hacer referencia la función extraída de la etiqueta personalizada.
    789 		 * @link sg.addCustomAttr Hacer referencia la función definida del atributo personalizado.
    790 		 */
    791 		addCustomTag: function( obj ){
    792 			customTagList[ obj.name ] = {
    793 				originTag: obj.originTag ? obj.originTag : "div",
    794 				identifier: obj.id ? obj.id : "data-sg-id='" + obj.name + "'",
    795 				eventName: obj.event,
    796 				attrList: (function( list ){
    797 					if( !list ) return null;
    798 					else list = slice.call( list );//copy array
    799 					var i=0, attrName;
    800 					list.forEach( function(attrName){
    801 						if( !(attrName in customAttrList) ) list.splice( i, 1 );
    802 						else i++;
    803 					});
    804 					return list;
    805 				})( obj.attr ),
    806 				initFunc: obj.init,
    807 				eachInitFunc: obj.tagInit,
    808 				eventFunc: obj.eventHandle
    809 			}
    810 		},
    811
    812 		//initialize about custom attribute in custom tag
    813 		/**
    814 		 * La función de inicialización sobre los atributos configurados al definir la etiqueta personalizada.
    815 		 * @function
    816 		 * @name initAttr
    817 		 * @memberOf sg
    818 		 * @example sg.initAttr( element );
    819 		 * @param {object} element
    820 		 */
    821 		initAttr: function( element ){
    822 			//console.log( element, arguments.callee );
    823 			var customTagName = $( element ).data( "_customTagName" )
    824 				, attrList, attr, attrValue;
    825
    826 			if( customTagName ){
    827 				attrList = customTagList[ customTagName ].attrList;
    828 				if( attrList ){
    829 					attrList.forEach(function( attrName ){
    830 						attr = customAttrList[ attrName ];
    831 						attrValue = element.getAttribute( "data-" + attrName );
    832 						if( attr && attr[ "init" ] && !attr.isForEveryTags ){
    833 							attr[ "init" ].call( element, element, attrValue );
    834 						}
    835 					});
    836 				}
    837 			}
    838 		},
    839
    840 		//execute function about custom attribute in custom tag
    841 		/**
    842 		 * Ejecuta la función action del atributo personalizado definedo en la etiqueta personalizada.
    843 		 * @function
    844 		 * @name actionAttr
    845 		 * @memberOf sg
    846 		 * @example sg.actionAttr( element );
    847 		 * @param {object} element
    848 		 */
    849 		actionAttr: function( element ){
    850 			var customTagName = $( element ).data( "_customTagName" )
    851 				, attrList, attr, attrValue;
    852
    853 			if( customTagName ){
    854 				attrList = customTagList[ customTagName ].attrList;
    855 				if( attrList ){
    856 					attrList.forEach(function( attrName ){
    857 						attr = customAttrList[ attrName ];
    858 						attrValue = element.getAttribute( "data-" + attrName );
    859 						if( attr && attr[ "action" ] ){
    860 							attr[ "action" ].call( element, element, attrValue );
    861 						}
    862 					});
    863 				}
    864 			}
    865 		},
    866
    867
    868
    869 		/**
    870 		 * jQuery.hide
    871 		 * @function
    872 		 * @name hide
    873 		 * @memberOf sg
    874 		 * @example
    875 		 * sg.hide( 'p' );	//$( 'p' ).hide();
    876 		 * sg.hide( this ); //$( this ).hide();
    877 		 * @param {object} elementOrSelector
    878 		 */
    879 		hide: function( elementOrSelector ){
    880 			$( elementOrSelector ).hide();
    881 		},
    882
    883 		/**
    884 		 * jQuery.show
    885 		 * @function
    886 		 * @name show
    887 		 * @memberOf sg
    888 		 * @example
    889 		 * sg.show( 'p' );	//$( 'p' ).show();
    890 		 * sg.show( this ); //$( this ).show();
    891 		 * @param {object} elementOrSelector
    892 		 */
    893 		show: function( elementOrSelector ){
    894 			$( elementOrSelector ).show();
    895 		},
    896
    897 		/**
    898 		 * jQuery.fadeIn("slow")
    899 		 * @function
    900 		 * @name fadeIn
    901 		 * @memberOf sg
    902 		 * @example
    903 		 * sg.fadeIn( 'p' );	//$( 'p' ).fadeIn( 'slow' );
    904 		 * sg.fadeIn( this );	//$( this ).fadeIn( 'slow' );
    905 		 * @param {object} elementOrSelector
    906 		 */
    907 		fadeIn: function( elementOrSelector ){
    908 			$( elementOrSelector ).fadeIn("slow");
    909 		},
    910
    911 		/**
    912 		 * jQuery.fadeOut("slow")
    913 		 * @function
    914 		 * @name fadeOut
    915 		 * @memberOf sg
    916 		 * @example
    917 		 * sg.fadeOut( 'p' );	//$( 'p' ).fadeOut( 'slow' );
    918 		 * sg.fadeOut( this );	//$( this ).fadeOut( 'slow' );
    919 		 * @param {object} elementOrSelector
    920 		 */
    921 		fadeOut: function( elementOrSelector ){
    922 			$( elementOrSelector ).fadeOut("slow");
    923 		},
    924
    925 		/**
    926 		 * Deshabilitar los eventos en el componente, y configura el cursor como puntero.
    927 		 * @function
    928 		 * @name enabled
    929 		 * @memberOf sg
    930 		 * @example
    931 		 * sg.enabled( this );
    932 		 * sg.enabled( '#myButton' );
    933 		 * sg.enabled( $.getCustomTag( 'sg-btn-hide' ) );
    934 		 * @param {object} elementOrSelector
    935 		 * @returns objeto de jQuery
    936 		 * @type jQuery Object
    937 		 */
    938 		enabled: function ( elementOrSelector ){
    939 			return $(elementOrSelector).each(function(i,e){
    940 				var $this = $(this);
    941 				$this.css("cursor","pointer");
    942 				var options = $this.data("options") || {};
    943 				options.enabled = true;
    944 				$this.data("options", options);
    945 			});
    946 		},
    947
    948 		/**
    949 		 * Deshabilitar los eventos en el componente, y configura el cursor por defecto.
    950 		 * @function
    951 		 * @name disabled
    952 		 * @memberOf sg
    953 		 * @example
    954 		 * sg.disabled( this );
    955 		 * sg.disabled( '#myButton' );
    956 		 * sg.disabled( $.getCustomTag( 'sg-btn-hide' ) );
    957 		 * @param {object} elementOrSelector
    958 		 * @returns objeto de jQuery
    959 		 * @type jQuery Object
    960 		 */
    961 		disabled: function ( elementOrSelector ){
    962 			return $(elementOrSelector).each(function(i,e){
    963 				var $this = $(this);
    964 				$this.css("cursor","default");
    965 				var options = $this.data("options") || {};
    966 				options.enabled = false;
    967 				$this.data("options", options);
    968 			});
    969 		}
    970 	});
    971
    972 	sg.extend({
    973 		/**
    974 		 * En el caso de que se pase la función (callback) como función de inicialización o parámetro, se ejecuta primero la inicialización y luego la función.<br>
    975 		 * En el caso de sg.init(), se ejecuta primero html content(contenido de html) internamente y la inicialización.<br>
    976 		 * Si hay algo que se debe ejecutar después de la inicialización, se pasa la función (callback) al parámetro de init().
    977 		 * @function
    978 		 * @name init
    979 		 * @memberOf sg
    980 		 * @example
    981 		 * sg.setStage( "#stage" );
    982 		 * sg.setScaleMode( "showall" );
    983 		 * sg.init();
    984 		 * @example
    985 		 * sg.setStage( "#stage" );
    986 		 * sg.setScaleMode( "showall" );
    987 		 * sg.init( function(){} );
    988 		 * @param {function} [callback=undefined]
    989 		 */
    990 		init: function ( callback ) {
    991 			function _init(){
    992 				//////setting
    993 				//console.log("setting");
    994 				$body = $( document.body );
    995
    996 				replaceTagList();
    997
    998 				if( setStageFunc ){
    999 					setStageFunc.apply( sg );
    1000 					setStageFunc = null;
    1001 				}
    1002
    1003 				///compatibility for old versions
    1004 				if( "init" in window && sg.isFunction( window[ "init" ] ) ){
    1005 					window[ "init" ].apply( window );
    1006 				}
    1007
    1008 				if( "initList" in window ){
    1009 					initCallbackList = initCallbackList.concat( window[ "initList" ] );
    1010 				}
    1011 				///
    1012
    1013 				initCallbackList.forEach( function( initFunc ){
    1014 					if( sg.isFunction( initFunc ) ) initFunc.apply( window );
    1015 				});
    1016
    1017
    1018 				$("[data-sg-id='progressImg']").remove();
    1019 				$content = $("[data-sg-id='content']").css( "visibility", "visible" );
    1020 				$stage = $("[data-sg-id='stage']");
    1021 				sg.isReady = true;
    1022
    1023 				setTimeout(function(){
    1024 					$window.trigger("resize");
    1025 				}, 0);
    1026 			}
    1027
    1028 			if( $.isReady ){
    1029 				_init.apply( window );
    1030 				if( sg.isFunction( callback ) ) callback.apply( window );
    1031 			}else{
    1032 				$( document ).ready(function(e) {
    1033                     _init.apply( window );
    1034 					if( sg.isFunction( callback ) ) callback.apply( window );
    1035                 });
    1036 			}
    1037 		}
    1038 	});
    1039
    1040 	window.sg = sg;
    1041
    1042 	return sg;
    1043 })();