{"id":13563019,"url":"https://github.com/QuickCorp/QCObjects","last_synced_at":"2025-04-03T19:32:10.501Z","repository":{"id":983192,"uuid":"36046445","full_name":"QuickCorp/QCObjects","owner":"QuickCorp","description":"Full Stack Javascript Framework for Modern Software Development","archived":false,"fork":false,"pushed_at":"2024-10-24T00:09:25.000Z","size":21596,"stargazers_count":40,"open_issues_count":10,"forks_count":11,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-10-24T13:27:40.629Z","etag":null,"topics":["accesibility","appbar","clean-code","cloud-native","components","framework","inclusive-coding","javascript","meta","metaprocessors","microfrontend","microservices","performance","qcobjects","qcobjects-cli","qcobjects-component","qcobjects-explainer-video","qcobjects-http2","qcobjects-loads","qcobjects-sdk"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/QuickCorp.png","metadata":{"files":{"readme":"README-es.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["jeanmachuca"],"patreon":"qcobjects","open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["http://sponsorsignup.qcobjects.dev/"]}},"created_at":"2015-05-22T01:48:57.000Z","updated_at":"2023-06-27T03:43:50.000Z","dependencies_parsed_at":"2024-01-14T03:46:24.021Z","dependency_job_id":"7d7a5382-3983-4a53-a600-e76bfa0ae135","html_url":"https://github.com/QuickCorp/QCObjects","commit_stats":{"total_commits":3429,"total_committers":11,"mean_commits":"311.72727272727275","dds":0.3829104695246428,"last_synced_commit":"0f477b0b25ce5eeac8dae51f8f8ba6b63f2e4666"},"previous_names":["quickgroup/qcobjects"],"tags_count":652,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuickCorp%2FQCObjects","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuickCorp%2FQCObjects/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuickCorp%2FQCObjects/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuickCorp%2FQCObjects/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/QuickCorp","download_url":"https://codeload.github.com/QuickCorp/QCObjects/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247065372,"owners_count":20877764,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accesibility","appbar","clean-code","cloud-native","components","framework","inclusive-coding","javascript","meta","metaprocessors","microfrontend","microservices","performance","qcobjects","qcobjects-cli","qcobjects-component","qcobjects-explainer-video","qcobjects-http2","qcobjects-loads","qcobjects-sdk"],"created_at":"2024-08-01T13:01:14.356Z","updated_at":"2025-04-03T19:32:10.144Z","avatar_url":"https://github.com/QuickCorp.png","language":"JavaScript","funding_links":["https://github.com/sponsors/jeanmachuca","https://patreon.com/qcobjects","http://sponsorsignup.qcobjects.dev/","https://www.patreon.com/join/qcobjects?","https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=UUTDBUQHCS4PU\u0026source=url)!","https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=UUTDBUQHCS4PU\u0026source=url"],"categories":["JavaScript"],"sub_categories":[],"readme":"![logo](https://qcobjects.dev/qcobjects_01.png)\n\n[![GitHub license](https://img.shields.io/github/license/QuickCorp/QCObjects.svg)](https://github.com/QuickCorp/QCObjects/blob/master/LICENSE.txt) [![](https://data.jsdelivr.com/v1/package/npm/qcobjects/badge)](https://www.jsdelivr.com/package/npm/qcobjects)  [![Badge for version for Visual Studio Code extension Quickcorp.QCObjects-vscode](https://vsmarketplacebadge.apphb.com/version/Quickcorp.QCObjects-vscode.svg)](https://marketplace.visualstudio.com/items?itemName=Quickcorp.QCObjects-vscode) [![Documentation Status](https://readthedocs.org/projects/qcobjects/badge/?version=latest)](https://qcobjects.readthedocs.io/?badge=latest) [![GitHub release](https://img.shields.io/github/issues/QuickCorp/QCObjects.svg)](https://github.com/QuickCorp/QCObjects/releases/) [![GitHub stars](https://img.shields.io/github/stars/QuickCorp/QCObjects.svg)](https://github.com/QuickCorp/QCObjects) [![npm version](https://badge.fury.io/js/qcobjects.svg)](https://badge.fury.io/js/qcobjects) ![apm: version](https://flat.badgen.net/apm/v/qcobjects-syntax?params) ![docker pulls](https://img.shields.io/docker/pulls/quickcorp/qcobjects.svg) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v1.4%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md)\n\n[![Become a Patreon ](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/join/qcobjects?)\n\n# QCObjects\n------------------------------------\nBienvenido a [QCObjects](https://qcobjects.dev). Un framework Open Source que empodera a los full-stack developers para hacer micro-servicios y micro-frontends dentro de una arquitectura N-Tier.\n\nCon QCObjects los desarrolladores están habilitados para programar front-end y back-end en conjunto usando una sintaxis común in pure JavaScript. It is cross-browser, cross-platform and cross-frame.\n\n[QCObjects ha sido presentado por British Herald como el marco más avanzado para el desarrollo de software moderno.](https://britishherald.com/qcobjects-the-first-world-class-tech-framework-made-in-south-america-is-meant-to-make-developers-happier-while-they-code/)\n\nEste documento es la documentacion referencial principal!\n\nEste repositorio y archivo léame está alojado en [https://qcobjects.dev](https://qcobjects.dev)\n\nEcha un vistazo a la página oficial de [QCObjects](https://qcobjects.com) at https://qcobjects.com\n\nEste proyecto se adhiere al Pacto Colaborador[code of conduct](CODE_OF_CONDUCT.md). Al participar, se espera que respete este código. Por favor reportar algún comportamiento inaceptable a info@quickcorp.cl.\n\n**Contributors are welcome!**\n\nPuedes contribuir a [QCObjects](https://qcobjects.dev) siguiendo el conjunto de pautas expresadas en el archivo [CONTRIBUTING.md](CONTRIBUTING.md)\n\n# Video Explicativo de QCObjects\n\nPara todos los que no tengan tiempo de leer esto hoy, aquí hay un pequeño video que explica que es QCObjects y que puedes hacer con el.\n\n[![QCObjects Explainer Video](https://img.youtube.com/vi/D0rftABPGvQ/0.jpg)](https://www.youtube.com/watch?v=D0rftABPGvQ \"QCObjects Explainer Video\")\n\n_________________________\n# Tabla de Contenidos\n\n\u003c!-- TOC depthFrom:1 depthTo:3 withLinks:1 updateOnSave:1 orderedList:0 --\u003e\n\n- [QCObjects](#qcobjects)\n- [Video Explicativo de QCObjects](#video-explicativo-de-qcobjects)\n- [Tabla de Contenidos](#tabla-de-contenidos)\n- [Principios](#principios)\n- [Características principales](#caracter%C3%ADsticas-principales)\n- [Características Adoptadas de Apps Web Progresivas (PWA)](#caracter%C3%ADsticas-adoptadas-de-apps-web-progresivas-pwa)\n\t- [Prevenir recursos Render-blocking](#prevenir-recursos-render-blocking)\n\t- [Carga de recursos On-Demand](#carga-de-recursos-on-demand)\n\t- [Lazy-loading de imágenes y componentes (usar atributo lazy-src en vez de src en tag img )](#lazy-loading-de-im%C3%A1genes-y-componentes-usar-atributo-lazy-src-en-vez-de-src-en-tag-img-)\n- [Cross Browser Javascript Framework para patrones MVC](#cross-browser-javascript-framework-para-patrones-mvc)\n- [Arquitectura de Componentes Dinámicos](#arquitectura-de-componentes-din%C3%A1micos)\n- [Especificación ECMA-262](#especificaci%C3%B3n-ecma-262)\n- [Copyright](#copyright)\n- [Demo](#demo)\n\t- [PWA Live Demo](#pwa-live-demo)\n\t- [Demo Integrada con Foundation](#demo-integrada-con-foundation)\n\t- [Demo Integrada con Materializecss](#demo-integrada-con-materializecss)\n\t- [Demo Usando Raw CSS](#demo-usando-raw-css)\n\t- [Ejemplo de QCObjects usando y manipulando objetos canvas](#ejemplo-de-qcobjects-usando-y-manipulando-objetos-canvas)\n- [DevBlog](#devblog)\n- [Fork](#fork)\n- [Conviértete en Sponsor](#convi%C3%A9rtete-en-sponsor)\n- [Revisa el SDK de QCObjects](#revisa-el-sdk-de-qcobjects)\n- [Donar](#donar)\n- [Instalar](#instalar)\n\t- [Usando QCObjects con Atom:](#usando-qcobjects-con-atom)\n\t- [Usando QCObjects con Visual Studio Code:](#usando-qcobjects-con-visual-studio-code)\n\t- [Instalando con NPM:](#instalando-con-npm)\n\t- [Instalando el docker playground:](#instalando-el-docker-playground)\n\t- [Script de instalación One-Step para Ubuntu 18.x](#script-de-instalaci%C3%B3n-one-step-para-ubuntu-18x)\n\t- [Script de instalación One-Step for macOS](#script-de-instalaci%C3%B3n-one-step-for-macos)\n\t- [Instalar y probar QCObjects en Sistema Operativo Microsoft Windows](#instalar-y-probar-qcobjects-en-sistema-operativo-microsoft-windows)\n\t- [Instalación QCObjects Multi-Cloud](#instalaci%C3%B3n-qcobjects-multi-cloud)\n\t\t- [DigitalOcean One-Click Droplet](#digitalocean-one-click-droplet)\n\t\t- [AWS Amazon Machine Images (AMI)](#aws-amazon-machine-images-ami)\n\t\t- [Amazon Web Services AWS PIB (Private Amazon Machine Image)](#amazon-web-services-aws-pib-private-amazon-machine-image)\n\t- [Usando el código de la versión de desarrollo directo en HTML5](#usando-el-c%C3%B3digo-de-la-versi%C3%B3n-de-desarrollo-directo-en-html5)\n\t- [Usando la versión minificada de código CDN desde jsDelivr](#usando-la-versi%C3%B3n-minificada-de-c%C3%B3digo-cdn-desde-jsdelivr)\n\t- [Usando la última versión no-minificada desde CDN jsDelivr](#usando-la-%C3%BAltima-versi%C3%B3n-no-minificada-desde-cdn-jsdelivr)\n\t- [Usando CDN UNPKG](#usando-cdn-unpkg)\n\t- [Usando CDNJS](#usando-cdnjs)\n- [Referencia](#referencia)\n\t- [QC_Object](#qc_object)\n\t- [ComplexStorageCache](#complexstoragecache)\n\t- [asyncLoad](#asyncload)\n\t- [Class](#class)\n\t- [Método QC_Append, append](#m%C3%A9todo-qc_append-append)\n\t- [El método \\_super\\_](#el-m%C3%A9todo-%5C_super%5C_)\n\t- [New](#new)\n\t- [InheritClass](#inheritclass)\n\t- [ClassFactory](#classfactory)\n\t- [\\_Crypt](#%5C_crypt)\n\t- [GLOBAL](#global)\n\t- [CONFIG](#config)\n\t- [Processor](#processor)\n\t- [waitUntil](#waituntil)\n\t- [Package](#package)\n\t- [Import](#import)\n\t- [Export](#export)\n\t- [Cast](#cast)\n\t- [Tag](#tag)\n\t- [Ready](#ready)\n\t- [Component Class](#component-class)\n\t- [Tag HTML Component](#tag-html-component)\n\t- [Controller](#controller)\n\t- [View](#view)\n\t- [VO](#vo)\n\t- [Service](#service)\n\t- [serviceLoader](#serviceloader)\n\t- [JSONService](#jsonservice)\n\t- [ConfigService](#configservice)\n\t- [SourceJS](#sourcejs)\n\t- [SourceCSS](#sourcecss)\n\t- [Effect](#effect)\n\t- [Timer](#timer)\n\t- [Funciones de lista y matemáticas](#funciones-de-lista-y-matem%C3%A1ticas)\n\t\t- [ArrayList](#arraylist)\n\t\t- [ArrayCollection](#arraycollection)\n\t\t- [[ArrayList or Array].unique](#arraylist-or-arrayunique)\n\t\t- [[ArrayList or Array].table](#arraylist-or-arraytable)\n\t\t- [[ArrayList or Array].sort](#arraylist-or-arraysort)\n\t\t- [[ArrayList or Array].sortBy](#arraylist-or-arraysortby)\n\t\t- [[ArrayList or Array].matrix](#arraylist-or-arraymatrix)\n\t\t- [[ArrayList or Array].matrix2d](#arraylist-or-arraymatrix2d)\n\t\t- [[ArrayList or Array].matrix3d](#arraylist-or-arraymatrix3d)\n\t\t- [range](#range)\n\t\t- [Array.sum](#arraysum)\n\t\t- [Array.avg](#arrayavg)\n\t\t- [Array.min](#arraymin)\n\t\t- [Array.max](#arraymax)\n\t- [SDK](#sdk)\n\t\t- [SDK Components](#sdk-components)\n\t\t- [SDK Controllers](#sdk-controllers)\n\t\t- [SDK Effects](#sdk-effects)\n\t\t- [SDK Misc Tools](#sdk-misc-tools)\n\t\t- [SDK Views](#sdk-views)\n\t\t- [SDK i18n messages](#sdk-i18n-messages)\n\t- [The QCObjects HTTP2 Built-In Server](#the-qcobjects-http2-built-in-server)\n\t\t- [Start serving your files with QCObjects](#start-serving-your-files-with-qcobjects)\n\t\t- [Principals of an N-Tier or Multitier architecture](#principals-of-an-n-tier-or-multitier-architecture)\n\t\t- [Micro-services Principals](#micro-services-principals)\n\t\t- [Backend settings in config.json](#backend-settings-in-configjson)\n\t\t- [Backend routing](#backend-routing)\n\t\t- [The QCObjects Microservice Class and Package](#the-qcobjects-microservice-class-and-package)\n\t\t- [Generating a Self-Signed Certificate with QCObjects](#generating-a-self-signed-certificate-with-qcobjects)\n\t\t- [Working with a Letsencrypt HTTPS certificate, Certbot and QCObjects](#working-with-a-letsencrypt-https-certificate-certbot-and-qcobjects)\n- [Quick Start Guide](#quick-start-guide)\n\t- [Quick Start your PWA (Progressive Web App)](#quick-start-your-pwa-progressive-web-app)\n\t- [Quick Start your AMP (Accelerated Mobile Page)](#quick-start-your-amp-accelerated-mobile-page)\n- [Start Coding](#start-coding)\n\t- [Step 1: Start creating a main import file and name it like: cl.quickcorp.js. Put it into packages/js/ file directory](#step-1-start-creating-a-main-import-file-and-name-it-like-clquickcorpjs-put-it-into-packagesjs-file-directory)\n\t- [Step 2: Then create some services inhereting classes into the file js/packages/cl.quickcorp.services.js :](#step-2-then-create-some-services-inhereting-classes-into-the-file-jspackagesclquickcorpservicesjs-)\n\t- [Step 3: Now it's time to create the components (cl.quickcorp.components.js)](#step-3-now-its-time-to-create-the-components-clquickcorpcomponentsjs)\n\t- [Step 4: Once you have done the above components declaration, you will now want to code your controllers (cl.quickcorp.controller.js)](#step-4-once-you-have-done-the-above-components-declaration-you-will-now-want-to-code-your-controllers-clquickcorpcontrollerjs)\n\t- [Step 5: To use into the HTML5 code you only need to do some settings between script tags](#step-5-to-use-into-the-html5-code-you-only-need-to-do-some-settings-between-script-tags)\n- [QCObjects CLI Tool](#qcobjects-cli-tool)\n\t- [Usage](#usage)\n\t- [Options](#options)\n\t- [Commands](#commands)\n\t- [Use:](#use)\n- [ALPHA RISE Startup](#alpha-rise-startup)\n\n\u003c!-- /TOC --\u003e\n\n\n\n# Principios\n\nAquí están Las directrices con lo que QCObjects fue hecho:\n\n0. Deberá escribir en JavaScript para codificar una aplicación JavaScript.\n1. Todo es un objeto.\n2. Cada objeto tiene una definición.\n3. En la interfaz, cualquier objeto puede ir apilado en el DOM o en el Virtual-DOM sin necesidad de redeclarar sus definiciones.\n4. Cada objeto tiene un cuerpo.\n5. La clase debería ser la definición principal de un objeto.\n6. La clase debería ser fácilmente escrita como un objeto.\n7. Tu Código debería estar fácilmente organizado en paquetes.\n8. Debería ser posible escalar sus aplicaciones a una arquitectura limpia.\n9. Un componente es una entidad que tiene un objeto como representación. El contenido de un componente debería ser posible rellenarlo remotamente como localmente. Como objeto el componente tiene cuerpo También y el cuerpo del componente es normalmente una instancia apilada del DOM element.\n10. Un componente puede ser adjunto al DOM o separado del el sin afectar a su funcionalidad.\n11. Un servicio de llamada puede ser extendido a escalar su funcionalidad.\n12. Deberías ser capaz de importar un paquete remotamente.\n13. Deberías poder escalar tu código y también controlar tus cambios en el servidor sin hacer llamadas innecesarias a fuentes remotas. No deberías necesitar codificar estos tipos de controles usted mismo.\n14. Deberías ser capaz de codificar tu aplicación N-Tier en un solo lenguaje o sintaxis.\n15. Deberías ser capaz de aplicar cualquier plantilla que quieras a un componente, no importa la sintaxis o el idioma en el que esta escrito.\n16. Si una etiqueta HTML esta ya representada por una instancia de objeto DOM, no deberías necesitar duplicar la defunción de la instancia para representar su contenido.\n17. Tu pagina principal HTML debería estar limpia, pero deberías poder enlazar lo que controla el comportamiento de la etiqueta sin afectar la sintaxis del HTML.\n18. El orden de ejecución de tu código debe ser fácil de entender y leer desde el codigo y el proceso de renderizado de cada componente debería tener y ejecutar control en cuantas capas necesites.\n19.Un patrón en capas(como el MVC o MVCC) debería estar presente para cada componente. No importa si defines cada capa o no.\n20. El comportamiento de un componente no debe estar determinado por su proceso de renderizado\n21. Es necesario que la pila de componentes se divida en el DOM hacia un árbol subyacente de elementos adjuntos.Entonces ahora existe y se llama Pila anidada de componentes de QCObject.\n22. Deberías ser capaz de extender una instancia de componente. Pero deberás ser capaz de controlar su comportamiento dinámico sin afectar a la declaración inicial.\n23. Deberías ser capaz de aplicar efectos visuales y animaciones simultaneas de una manera facil a una instancia de elemento DOM.\n24. Deberías ser capaz de controlar los efectos visuales y animaciones de CSS como JavaScript sin afectar a su desempeño.\n25.Deberías ser capaz de controlar el comportamiento de tu código Into-the-box y out-of-the-box y sobrevivir haciéndolo.\n\n# Características principales\n\n\n- Plantillas Built-In personalizadas para Progressive Web Apps (PWA) y Accelerated Mobile Pages (AMP)\n- Efectos UI revolucionarios.\n- Backend de micro-servicios avanzados.\n- La simplicidad de un maravilloso diseño de layouts.\n- Herramientas CLI completamente re-utilizables.\n- Arquitectura orientada a componentes y objetos\n- Front-end y back-end juntos en un entorno Full-Stack\n- Routing recursivo para componentes.\n- Administración de componentes anidados Built-In\n- Patron MCV completamente integrado (Model, View, Controller)\n- Objetos de datos dinamicos\n- Conceptos basados en la arquitectura N-Tier\n\n# Características Adoptadas de Apps Web Progresivas (PWA)\n\n## Prevenir recursos Render-blocking\n\nPara prevenir los recursos Render-blocking , QCObjects ha implementado la función de fabrica [paquete](#Package)\n\n## Carga de recursos On-Demand\n\nCon la arquitectura orientada a los componentes dinámicos, QCObjects renderiza cada recurso visual que esta dentro de un componente, solo cuando el componente se esta construyendo y cada componente esta conectado a un árbol llamado global.componentsStack ese es el que realmente esta apuntando a cada instancia de componente y sus a sus sub componentes. Cada vez que un componente es re-hecho, los recursos visuales están dinámicamente recargados bajo demanda de la manera mas eficiente, así que puedes olvidar esos horribles códigos donde necesitabas controlar el proceso de recarga de los recursos con otros frameworks.\n\n## Lazy-loading de imágenes y componentes (usar atributo lazy-src en vez de src en tag img )\n\nDesde la versión 2.1.251, QCObjects te otorga una forma fácil para el Lazy load de imágenes, usando el ultima estándar para los buscadores.\n\n```html\n\u003cimg src=\"img/preloader.svg\" lazy-src=\"img/myrealimage.png\"/\u003e\n```\nEn lo anterior, una imagen (ligera) precargada, es usada para ser cargada en la primera instancia y un atributo **lazy-src** es usado para cargar la imagen real después del proceso Lazy load. QCObjects cargara todos las **\u003cimg\u003e** etiquetas declaradas dentro de un componente en el lazy mode si tiene un atributo lazy-src, después que un componente es rearmado o cargado. También, QCObjects usara [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) (Cuando este disponible) para determinar ya sea si el lazy-src o la imagen src son visualmente útiles para ser mostradas.\n\nEl efecto del Lazy loading es altamente visible solo si la primera vez el PWA es cargado. La próxima vez, la velocidad de carga aumentara significativamente haciendo difícil para el ojo humano ver el resultado. Sin embargo esta característica hará mucho la diferencia en términos de experiencia de usuario, si existen problemas de conexión o las imágenes son muy grandes esta característica es parte de las recomendadas por os escritores de PWA por [Mozzila Developers Network](https://developer.mozilla.org/) un articulo sobre Loadig progresivo. Puedes leer el articulo [here](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Loading)\n\nSi no quieres usar lazy loading para las imágenes, siempre puedes mantener la forma usual de carga no añadiendo el atributo **lazy-src**  a la etiqueta **\u003cimg\u003e** y usando el tradicional **src**.\n\n\n# Cross Browser Javascript Framework para patrones MVC\n----------------------------------------\n\n[QCObjects](https://qcobjects.dev)Es un framework de Javascript diseñado para hacer todo mas fácil sobre la implementación de los MVC patters en el alcance de pure Javascript. No necesitas utilizar un typescript ni ningún transpiler para que corra. [QCObjects](https://qcobjects.dev). Corre directamente en el buscador y usa pure javascrpt sin ninguna dependencia de código extra. Puedes crear tus propios componentes expresados en objetos nativos reales de Javascript o  objetos nativos DOM extendidos para usarlos a tu manera. Puedes también usar QCObjects](https://qcobjects.dev) En conjunto con CSS3 frameworks como [Foundation] (https://foundation.zurb.com), [Bootstrap] (https://getbootstrap.com) Y frameworks de mobil javascript como [PhoneGap] (https://phonegap.com) y OnsenUI (https://onsen.io)\n\n![screenshot](https://qcobjects.dev/doc/img/components.gif)\n\n# Arquitectura de Componentes Dinámicos\n\n![qcobjects components layout](https://qcobjects.dev/doc/img/QCObjects-Components-Layout.gif)\n\n\n# Especificación ECMA-262\n--------------------------\nSee\n[ECMAScript® 2020 Language Specification](https://tc39.github.io/ecma262/#sec-intro) como referencia.\n\n# Copyright\n-----------\n\nCopyright (c) Jean Machuca and [QuickCorp](https://quickcorp.org) \u003cinfo@quickcorp.cl\u003e\n\n# Demo\n--------------\n\n## PWA Live Demo\n\nMira esta demo en vivo de pure QCObjects basado en aplicación web fronted aquí:\n[PWA QCObjects](https://newapp.qcobjects.dev/)\n\n## Demo Integrada con Foundation\n\nA continuación, una demostración en vivo usando componentes de Foundation aquí:\n[Demo usando Foundation](https://github.com/QuickCorp/quickobjects_sample1foundation)\n\n## Demo Integrada con Materializecss\n\nRevisa la demostración usando  MaterializeCSS aquí:\n[Demo Using Materializecss](https://qln.link)\n\n## Demo Usando Raw CSS\n\nRevisa esta demo usando raw CSS aquí:\n[Demo Using Raw CSS](https://github.com/QuickCorp/qcobjects_profile_browser)\n\n## Ejemplo de QCObjects usando y manipulando objetos canvas\n\nA continuación el código muestra como QCObjects puede manipular un objeto de lienzo directamente y dentro de componentes\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n    \t\u003ctitle\u003eDemo\u003c/title\u003e\n    \t\u003cscript type=\"text/javascript\" src=\"https://qcobjects.dev/QCObjects.js\"\u003e\u003c/script\u003e\n    \t\u003cscript type=\"text/javascript\"\u003e\n    \t\tvar canvas1,canvas2,canvas3,container;\n        CONFIG.set('relativeImportPath','src/');\n\n    \t\t/**\n    \t\t * Main import sentence.\n    \t\t */\n    \t\tImport('cl.quickcorp',function (){\n\n    \t\t\t/**\n    \t\t\t * Super Container MyOwnBody\n    \t\t\t */\n\t    \t\tClass('MyOwnBody',HTMLBodyElement,{\n\t    \t\t\tcustomAttr:'custom',\n\t    \t\t\tbody:document.body  // breakes default body element and replace with them\n\t    \t\t});\n\n\t    \t\t/**\n\t    \t\t * Another custom class definition\n\t    \t\t */\n\t    \t\tClass('MyContainer',HTMLElement,{\n\t    \t\t\twidth:400,\n\t    \t\t\theight:400,\n\t    \t\t\tcustomAttr:'custom attr container'\n\t    \t\t});\n\n\n\t    \t\t/**\n\t    \t\t * Another custom class definition\n\t    \t\t */\n\t    \t\tClass('canvas',HTMLCanvasElement,{\n\t    \t\t\tcustomAttr:'custom'\n\t    \t\t});\n\n\t    \t\t/**\n\t    \t\t * Another custom class definition\n\t    \t\t */\n\t    \t\tClass('MyCanvas2',HTMLCanvasElement,{});\n\n\t    \t\tbody = New(MyOwnBody); // binds to body\n\t    \t\tbody.css({backgroundColor:'#ccc'});\n\n\t    \t\tcontainer = Tag('container')[0].Cast(MyContainer); // cast any javascript dom object to QC_Object class\n\t    \t\tcontainer.css({backgroundColor:'red'}); // access binding in two directions to dom objects\n\n\t    \t\t/**\n\t    \t\t * Instance a new custom canvas\n\t    \t\t */\n\t    \t\tcanvas1 = New(canvas,{\n            width:100,\n            height:100,\n          });\n\t    \t\tcanvas2 = New(canvas,{\n            width:200,\n\t    \t\t\theight:100,\n          });\n\t    \t\tcanvas3 = New(canvas,{\n            width:300,\n\t    \t\t\theight:50,\n          });\n\n\t    \t\tcanvas1.css({backgroundColor:'#000000'}); // like jquery and another style access\n          canvas1.body.style.backgroundColor='#000000'; // standard javascript style access\n\t    \t\tcanvas2.body.style.backgroundColor='#0044AA'; // standard javascript style access\n\t    \t\tcanvas3.body.style.backgroundColor='green'; // standard javascript style access\n\n\t    \t\tcanvas1.append(); //append canvas1 to body\n\t    \t\tcanvas2.attachIn('container'); // attach or append to specific tag containers\n\t    \t\tcontainer.append(canvas3); // append canvas3 to custom tag binding\n\n//\t    \t\tcanvas1.body.remove(); // remove canvas1 from dom\n\t    \t\tbody.append(canvas3); // append canvas3 to body\n\n          // using components\n          var c1 = New(Component,{'templateURI':'templatesample.html',cached:false});\n          document.body.append(c1); // appends the c1 to the body\n\n\n    \t\t});\n\n    \t\u003c/script\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n    \t\u003ccontainer id=\"contentLoader\" \u003e\u003c/container\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n# DevBlog\n--------------\nel [Official DevBlog of QCObjects](https://devblog.qcobjects.org/) esta alojado en [Hashnode](https://hashnode.com/). El DevBlog esta personalmente escrito por Jean Machuca, el autor de [QCObjects](https://qcobjects.com) Y el esta explicando en detalle como son las mejores practicas y dando los mejores tips y trucos para usar las mas avanzadas características de QCObjects.\n\n# Fork\n--------------\nPor favor has Fork a este projecto o crea un link a este proyecto en to archivo README.md. Lee el archivo LICENSE.txt antes de usar este código.\n\n# Conviértete en Sponsor\n------------------\nSi quieres volverte sponsor de este maravilloso proyecto puedes hacerlo [aquí](https://sponsorsignup.qcobjects.dev/)\n\n# Revisa el SDK de QCObjects\n----------------------------\nPuedes revisar[QCObjects SDK](https://sdk.qcobjects.dev/) y seguir los ejemplos para hacer tus propios componentes destacados.\n\n\n# Donar\n--------------\n\nSi te gustó este código por favor [DONA](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=UUTDBUQHCS4PU\u0026source=url)!\n\n [![paypal](https://www.paypalobjects.com/webstatic/mktg/logo/AM_mc_vs_dc_ae.jpg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=UUTDBUQHCS4PU\u0026source=url)\n\n [![vuelvete patreon ](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/join/qcobjects?)\n\n\n# Instalar\n------------\n\n\n## Usando QCObjects con Atom:\n\n```shell\n\u003e apm install qcobjects-syntax\n```\nhttps://atom.io/packages/qcobjects-syntax\n\n## Usando QCObjects con Visual Studio Code:\n\n[![Badge for installs for Visual Studio Code extension Quickcorp.QCObjects-vscode](https://vsmarketplacebadge.apphb.com/version/Quickcorp.QCObjects-vscode.svg)](https://marketplace.visualstudio.com/items?itemName=Quickcorp.QCObjects-vscode)\n\nhttps://marketplace.visualstudio.com/items?itemName=Quickcorp.QCObjects-vscode\n\n## Instalando con NPM:\n\n```shell\n\u003e npm install qcobjects-cli -g \u0026\u0026 npm install qcobjects --save\n```\n![screenshot2](https://qcobjects.dev/doc/img/QCObjects-Quick-Start.gif)\n\n## Instalando el docker playground:\n\n```shell\ndocker pull -a quickcorp/qcobjects-playground \u0026\u0026 docker run -it --name qcobjects-playground --rm -it quickcorp/qcobjects-playground\n```\n\n![screenshot3](https://qcobjects.dev/doc/img/QCObjects-Docker-Playground.gif)\n\n## Script de instalación One-Step para Ubuntu 18.x\nATENCIÓN: Haz esto solo en una instalación de Ubuntu 18.x fresca/vacia/actual. No lo haga en un ambiente existente de producción.\n Se te pedira permiso sudo grant.\n\n```shell\ncurl -L https://qcobjects.dev/install_qcobjects_ubuntu18x.sh |sh\n```\nATENCIÓN: No somos responsables de el daño en la infraestructura por usar una instalación automatizada de script en una network insegura. Asegúrate de que tus repos y scripts están bajo HTTPS con su certificado valido. Para mejores resultados te recomendamos descargar el script, editarlo para tus necesidades especiales y después ejecútalo en tu maquina local.\n\n## Script de instalación One-Step for macOS\nProbado en macOS Catalina 10.15.3\n\n```shell\ncurl -L https://qcobjects.dev/install_qcobjects_macOS.sh | zsh\n```\n\n## Instalar y probar QCObjects en Sistema Operativo Microsoft Windows\n\n1.- Instala la ultima versión de NodeJS para Windows[Aquí](https://nodejs.org/)\n2.- Desde el cmd instala qcobjects-cli usando npm\n\n\n```powershell\nnpm i qcobjects-cli -g\n```\n3.- Crea un directorio de para tu proyecto\n\n```powershell\nmd mynewproject \u0026\u0026 cd mynewproject\n```\n4.- Crea una nueva aplicación web progresiva de QCObjects\n\n```powershell\nqcobjects create mynewproject --pwa\n```\n\n![screenshot](https://qcobjects.dev/doc/img/QCObjects-running-on-Windows64bit.gif)\n\n\n## Instalación QCObjects Multi-Cloud\n\nQCObjects es nativamente soportado por los mas famosos proveedores de nubes. Puedes instalar la mayoría de ellos, preparar y correr todo en un solo paso.\n\n### DigitalOcean One-Click Droplet\n\nSi quieres olvidar apt-get y de configurar la guía, ve directo a desplegar tu proyecto usando una preconfigurada app 1-click incluyendo QCObjects CLI, QCObjects-SDK y QCObjects HTTP2 servidor Built-in. Luego giralo a Droplet VM o a Kubernetes cluster en 60 segundos o menos.\n\n[Crea tu propio Droplet de QCObjects DigitalOcean Aquí](https://marketplace.digitalocean.com/apps/qcobjects)\n\n### AWS Amazon Machine Images (AMI)\n\nUn Amazon Machine Image (AMI) otorga información requerida para lanzar una instancia.  Tienes que especificar un AMI cuando quieras lanzar una instancia. Puedes lanzar múltiples instancias para un solo AMI cuando necesites múltiples instancias con la misma configuración. Puedes usar diferentes AMIs para lanzar instancias cuando necesites instancias con diferentes configuraciones.\n\nUn AMI incluye lo siguiente:\n\n- Uno o mas EBS snapshots, o, para instance-store-backed AMIs, una plantilla para la raíz volumen de la instancia(por ejemplo, un sistema operativo, un servidor de aplicaciones y aplicaciones).\n- Lanza permisos que controla que cuenta AWS puede usar el AMI para lanzar instancias.\n- Un bloqueo de dispositivos mapping que especifica los volúmenes adjuntos a la instancia cuando es lanzada.\n\n[Empieza construyendo QCObjects AMI aquí](https://aws.amazon.com/marketplace/pp/B07YZRH7VB)\n\n### Amazon Web Services AWS PIB (Private Amazon Machine Image)\n\n\nImagen privada que te permite construir un nuevo AMI instalando un software AWS Market place en una imagen que tu elijas del AMI disponibles en tu cuenta AWS, esto permite que conocer a mejores especificaciones internas para seguridad, gestiones y cumplimientos.  Como con los Marketplace AWS AMIs estándar, cada imagen privada se comprometera a subscripción por el producto instalado y tiene uso de software facturado vía AWS Marketplace.\n\n[Empieza creando tu QCObjects Amazon Private Image aquí](https://aws.amazon.com/marketplace/pp/B07YZRH7VB)\n\n\n## Usando el código de la versión de desarrollo directo en HTML5\n\n```html\n\u003cscript type=\"text/javascript\" src=\"https://qcobjects.dev/QCObjects.js\"\u003e\u003c/script\u003e\n```\n\n## Usando la versión minificada de código CDN desde jsDelivr\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/qcobjects/QCObjects.min.js\"\u003e\u003c/script\u003e\n```\n\n## Usando la última versión no-minificada desde CDN jsDelivr\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/qcobjects/QCObjects.js\"\u003e\u003c/script\u003e\n```\n\n## Usando CDN UNPKG\n\n```html\n\u003cscript src=\"https://unpkg.com/qcobjects@latest/QCObjects.js\"\u003e\u003c/script\u003e\n```\n\n## Usando CDNJS\n\n```html\n\u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/qcobjects/[VERSION]/QCObjects.js\"\u003e\u003c/script\u003e\n```\n\nDonde [VERSIÓN] corresponde a la ultima versión usando notaciones numericas, ejemplo: to use version 2.1.420:\n\n```html\n\u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/qcobjects/2.1.420/QCObjects.js\"\u003e\u003c/script\u003e\n```\n\nNo necesitas minificar QCObjects, pero si aún quieres usar el codigo minificado puedes hacer esto:\n\n```html\n\u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/qcobjects/2.1.420/QCObjects.min.js\"\u003e\u003c/script\u003e\n```\n\nOtra vez cambia 2.1.420 al numero de la versión que quieras usar.\n\n\n# Referencia\n------------\n\nAquí están los símbolos y conceptos esenciales de referencia [QCObjects](https://qcobjects.dev)\n\n### QC_Object\n\nTipos básicos de todos los elementos\n\n### ComplexStorageCache\n\nCon **ComplexStorageCache** puedes manejar el cache de cualquier objeto y subirlo en el storage local.\n\n#### Uso:\n```javascript\nvar cache = new ComplexStorageCache({\n                      index:object.id, // Object Index\n                      load:(cacheController)=\u003e{}, // A function to execute for the first time\n                      alternate: (cacheController)=\u003e{} // The alternate function to execute from the second time the source coude is loaded\n                      });\n```\n\n#### Ejemplo:\n```javascript\nvar dataObject = {id:1,\n                  prop1:1,\n                  prop2:2\n                };\n\nvar cache = new ComplexStorageCache({\n    index: dataObject.id,\n    load: (cacheController) =\u003e {\n      dataObject = {\n              id:dataObject.id,\n              prop1:dataObject.prop1*2, // changing a property value\n              prop2:dataObject.prop2\n            };\n      return dataObject;\n    },\n    alternate: (cacheController) =\u003e {\n      dataObject = cacheController.cache.getCached(dataObject.id); // setting dataObject with the cached value\n      return;\n    }\n  });\n\n// Next time you can get the object from the cache\nvar dataObjectCopyFromCache = cache.getCached(dataObject.id);\nconsole.log(dataObjectCopyFromCache); // will show the very same object value than dataObject\n```\n\n### asyncLoad\n\nLa función **asyncLoad** carga el código una vez en el modo asyc. Esto es útil para asegurar que el proceso inicial no replica la ejecución y no es recargado después de un código sensible.\n\n#### Uso:\n```javascript\nasyncLoad(()=\u003e{\n  // my code here\n},args);\n// Where args is an array of arguments, it can be the \"arguments\" special object\n```\n\n#### Ejemplo:\n```javascript\n\nlet doSomething = (arg1,arg2)=\u003e{\n  asyncLoad((arg1,arg2)=\u003e{\n    console.log(arg1);\n    console.log(arg2);\n  },arguments);\n};\n\ndoSomething(1,2); // the code of doSomething will be executed once after the rest of asyncLoad queue of functions and before the execution of Ready event.\n\n```\n\n\n### Class\n\nEsto NO es una clase de definición de ECMAScript 2015 (mira [clase ECMAScript 2015](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) for reference).\n\nClase es una función especias que te ayuda a declarar la clase de una manera mas fácil y compatible. Funciona con cross-browser, y esperamos que ECMA pueda adoptar algo similar en el futuro. Para no dejar al Javascript confuso sobre esto, [QCObjects](https://qcobjects.dev) usa \"Class\" no \"class\" (note the Camel Case).\n\n\n#### Uso:\n\n```javascript\nClass('MyClassName',MyClassDefinition);\n```\nDonde **MyClassDefinition** es un objeto junto a el **prototype** de QCObjects\n\n#### Ejemplo:\n```javascript\nClass('MyClassName',InheritClass,{\n  propertyName1:0, // just to declare purpose\n  propertyName2:'',\n  classMethod1: function (){\n    // some code here\n    // note you can use \"this\" object\n    return this.propertyName1;\n  },\n  classMethod2: function () {\n    // some code here\n    return this.propertyName2;\n  }\n});\n\nvar newObject = New(MyClassName,{\n    propertyName1:1, // this initializes the value in 1\n    propertyName2:\"some value\"\n});\nconsole.log(newObject.classMethod1()); // this will show number 1\nconsole.log(newObject.classMethod2()); // this will show \"some value\"\n\n```\n\n\n### Método QC_Append, append\n\nEste es un método especial que hará tu vida mas fácil cuando quieras manipular el **DOM** dinámicamente. Puedes insertar un componente incluso **Component**, a un objeto **QCObjects** o a el elemento **DOM** dentro de otro **HTMLElement**.\n\n##### Uso:\n```javascript\n[element].append([object or element]);\n```\n#### Ejemplo:\n```javascript\n// This will create a QCObjects class named \"canvas\" extending a HTMLCanvasElement with a customAttr property that has a \"custom\" value\nClass('canvas',HTMLCanvasElement,{\n  customAttr:'custom'\n});\n\n// This will declare an instance canvas1 from the class canvas\nlet canvas1 = New(canvas,{\n            width:100,\n            height:100,\n          });\n\n// This will append the canvas1 object to the document body\ndocument.body.append(canvas1);\n\n```\n\n\n\n### El método \\_super\\_\n\nCuando extiendes una clase QCObject desde otra, puedes usar \\_super\\_ metodo para tener una instancia desde la definición de la clase central.\n\n#### Uso:\n```javascript\n\n_super_('MySuperClass','MySuperMethod').call(this,params)\n// where this is the current instance and params are method parameters\n```\n\n#### Ejemplo:\n```javascript\nClass('MySuperiorClass',InheritClass,{\n  propertyName1:0, // just to declare purpose\n  propertyName2:'',\n  classMethod1: function (){\n    // some code here\n    // note you can use \"this\" object\n    return this.propertyName1;\n  },\n});\n\nClass('MyClassName',MySuperiorClass,{\n  propertyName1:0, // just to declare purpose\n  propertyName2:'',\n  classMethod2: function () {\n    // The next line will execute classMethod1 from MySuperiorClass\n    // but using the current instance of MyClassName1\n    return _super_('MySuperiorClass','classMethod1').call(this);\n  }\n});\n\nvar newObject = New(MyClassName,{\n    propertyName1:1, // this initializes the value in 1\n    propertyName2:\"some value\"\n});\nconsole.log(newObject.classMethod2()); // this will show the number 1\n```\n\n### New\n\nCrea una instancia de objeto de una definición de clase de QCObject.\n\n#### Uso:\n\n```javascript\nlet objectInstance = New(QCObjectsClassName, properties);\n// where properties is a single object with the property values\n```\nNOTA: En las propiedades del objeto puedes usar un solo valor o un captador también pero, solo se ejecutaran una vez.\n\n#### Ejemplo:\n\n```javascript\nClass('MyCustomClass',Object);\nlet objectInstance = New(MyCustomClass,{\n  prop1:1,\n  get randomNumber(){ // this getter will be executed once\n    return Math.random();\n  }\n});\n\nconsole.log(objectInstance.randomNumber); // it will show console.log(objectInstance.prop1); // it will show number 1\n```\n\n\n### InheritClass\nUna sola definición de clase común QCObjects es utilizada.\n\n### ClassFactory\nUsa la **ClassFactory** para tener una declaración de clase de fabrica para la clase,\ntambién puedes usar la clase de fabrica desde un paquete o desde la fila apilada.\n\nPara recuperar la clase de fabrica de la clase fila apilada simplemente usa el nombre de la clase llamándola directamente en el código.\n\n#### Ejemplo:\n\n```javascript\n/* When you declare MyClass using Class() it is instantly added to the Class queue stack\n* and you can get the factory either using ClassFactory() or calling the name MyClass straight in the code\n*/\nClass('MyClass',{\n\ta:1\n})\nconsole.log(MyClass == ClassFactory('MyClass')) // it will show true\n```\n\n```javascript\n/* On the other hand, ClassFactory() will be so useful when you define a Class into a Package\n*/\nPackage('org.quickcorp.package1',[\n\tClass('MyClass',{\n\t\ta:1\n\t})\n])\nconsole.log(MyClass == ClassFactory('MyClass')) // it will still show true\n// The following line will show true as well\nconsole.log(MyClass == ClassFactory('org.quickcorp.package1.MyClass'))\n```\n\n```javascript\n/* The interesting thing is when you have declared more than one Class using the\n* same name MyClass into different packages but with different property default values\n* and even properties\n*/\nPackage('org.quickcorp.package1',[\n\tClass('MyClass',{\n\t\ta:1\n\t})\n])\nPackage('org.quickcorp.package2',[\n\tClass('MyClass',{\n\t\ta:2,\n\t\tb:1\n\t})\n])\n// The last declaration of MyClass will be the one survival in the Class queue\n// so the reference MyClass in the code will point to that one\nconsole.log(MyClass == ClassFactory('MyClass')) // it will still show true\n\n// In this case as the MyClass defined in the org.quickcorp.package1 will not be the same\n// as the one in the org.quickcorp.package2, but the MyClass in the package2 is the last one\n// The following line will show false\nconsole.log(MyClass == ClassFactory('org.quickcorp.package1.MyClass'))\n\n// The following line will show true\nconsole.log(MyClass == ClassFactory('org.quickcorp.package2.MyClass'))\n\n// The following line will show false\nconsole.log(ClassFactory('org.quickcorp.package1.MyClass') == ClassFactory('org.quickcorp.package2.MyClass'))\n```\n\nLos ejemplos anteriores están intencionalmente hechos para explicar y mostrar como el alcance de la definición de clase en QCObjects es protejida, llevada y reflejada en una ClassFactory.\n\nAsí que vas a querer usar la ClassFactory cuando necesites completar un control sobre el alcance cuando se extienden las Clases.\n\n**Ejemplo**\n\n```javascript\n// When normally you extend a Class using the Class queue you do:\nClass('MyExtendedClass',MyInheritClass,{\n\textendedProp1: 'value of prop',\n\textendedProp2: 2\n})\n\n```\n\n```javascript\n/* But to protect the scope from misleading by reference, you can asure that MyInheritClass\nis the one you want to extend by declaring it into a package and then extend it\n*/\nPackage('org.quickcorp.mypackage1',[\n\tClass('MyInheritClass',{\n\t\tsourceProp:1\n\t}),\n])\n\n// The following code is a definition of MyExtendedClass into a different package\n// org.quickcorp.package2\n// extending MyInheritClass using ClassFactory to retreive the Class from the source package\n// org.quickcorp.mypackage1\nPackage('org.quickcorp.mypackage2',[\n\tClass('MyExtendedClass',ClassFactory('org.quickcorp.mypackage1.MyInheritClass'),{\n\t\textendedProp1: 'value of prop',\n\t\textendedProp2: 2\n\t})\n])\n\n// this will show the number 1 (as the inherited default value of sourceProp)\nconsole.log(New(MyExtendedClass).sourceProp)\n\n```\n\n### \\_Crypt\nCon \\_Crypt puedes codificar en serie objetos a passphrase\n\n#### Ejemplo (1):\n\n```javascript\n var _string = New(_Crypt,{string:'hello world',key:'some encryption md5 key'});\n console.log(_string._encrypt());\n console.log(_string._decrypt()); // decodes encrypted string to the source\n ```\n #### Ejemplo (2):\n\n ```javascript\n _Crypt.encrypt('hola mundo','12345678866');\n _Crypt.decrypt('nqCelFSiq6Wcpw==','12345678866');\n```\n\n\n### GLOBAL\n\n**GLOBAL** es una clase especial de QCObject para conseguir alancé global. Tiene un conjunto y consigue un método que te ayude a manejar propiedades internas Globales.\n\n#### Ejemplo:\n\n```javascript\nGLOBAL.set('globalProperty1','some value in global scope');\nvar globalProperty1 = GLOBAL.get('globalProperty1');\n```\n\n### CONFIG\n\nCONFIG es una clase inteligente que maneja los ajustes generales de tu aplicación. Puedes tener las propiedades ya sea desde config.json o desde la memoria previamente guardado en la llamada set().\n\n#### Uso desde memoria:\n\n1.- En su código inicial, configura los valores iniciales de CONFIG:\n```javascript\nCONFIG.set('someSettingProperty','some initial value');\n```\n2.- Luego puede acceder a él desde cualquier parte de su código utilizando el método get:\n```javascript\nvar someSettingProperty = CONFIG.get('someSettingProperty');\n```\n\n#### Uso desde config.json:\n\n1.- Necesitas indicar primero que estas usando el archivo config.jso mediante el ajuste \"useConfigService\" el valor para la verdad.\n\n```javascript\nCONFIG.set('useConfigService',true); // using config.json for custom settings config\n```\n2.-Una vez  peparaste el valor anterior QCObjects lo sabra y mirara el siguiente ajuste dentro del archivo config.json en la carpeta basePath de tu aplicación.\n\n#### Uso desde config.json encriptado:\n\nTambién existe una forma de usar el archivo encriptado config.json con el fin de proteger tus ajustes, robots que pueden robar tu data no protegida desde la aplicación web (como las llaves de arrastre API)\n\nEl archivo encriptado json va en https://config.qcobjects.dev, pon tu configuración dominantes y tu contenido config.json. La herramienta encriptará tu json y podrás copiar el contenido incriptado para insertarlo en tu archivo config.json. QCObjects sabrá si la data esta encriptada y tu proceso para decodificar la data sera mas transparente para ti.\n\n#### Propiedades dinámicas de CONFIG\n\nA veces necesitaras establecer el valor de la fuente que no sea estática, como el ENV vars u otras fuentes personalizadas de data dinámica. Para tener valor usando CONFIG de una fuente dinámica tienes que usar un procesador. Existen procesadores comunes predefinidos como $ENV (solo si esta disponible en CLI, Collab o Node) y $config (disponible en todos los ambientes).\n\nLos procesadores son llamados como una meta de valor ya sea en el config.json o en la Clase CONFIG.\n\n```json\n// file: config.json\n{\n\t\"domain\":\"localhost\",\n\t\"env1\":\"$ENV(ENV1)\",\n\t\"customSettings\":{\n\t\t\"value1\":\"$config(domain)\"\n\t}\n}\n```\n\n```javascript\nlet value1 = CONFIG.get(\"customSettings\").value1;\n// value1 = \"localhost\";\n\nlet env1 = CONFIG.get(\"env1\");\n//env1 = (environment variable ENV1)\n```\n\n```javascript\n// sets the key \"api_key\" of the CONFIG settings to a dynamic processor $ENV that recovers the value of API_KEY from the environment variables\nCONFIG.set(\"api_key\",\"$ENV(API_KEY)\");\n\nlet api_key = CONFIG.get(\"api_key\");\n// api_key will contain the value of the system API_KEY environment var\n// ($ENV processor returns a valid value only on Node.js , QCObjects CLI and QCObjects Collab engine)\n```\n\n### Processor\n\nLa clase estatica que usa para establecer el procesador personalizado para CONFIG.\n\n#### Uso:\n\n```javascript\nProcessor.setProcessor(processor)\n```\n\nDonde **processor** es el nombre de la función que recibe el argumento del procesador\n\n#### Ejemplo:\n\nTienes que usar ese valor en tus ajustes de configuración en el valor **serviceURL** pero también necesitas configurar el **host** y los ajustes de **port** usando el valor analizado de esa url. Para analizar el valor de el ambiente SERVICE_URL la variable bajo demanda y rellenarlo con los ajustes de configuración en tu config.json, tu config.json se vera algo así:\n ```json\n// file: config.json\n{\n\t\"serviceURL\":\"$ENV(SERVICE_URL)\",\n\t\"host\":\"$SERVICE_HOST(SERVICE_URL)\",\n\t\"port\":\"$SERVICE_PORT(SERVICE_URL)\"\n}\n```\n\nEl **$SERVICE_HOST** y el **$SERVICE_PORT** procesadores no existen. Para definirlos tienes que usar:\n\n```javascript\n// execute the next code in your init.js file or before to load the CONFIG settings\n\nlet SERVICE_HOST = function (arg){\n\tvar processorHandler = this; // to make this always works, do not use arrow functions to define your\n\tlet serviceURL = new URL(processorHandler.processors.ENV(arg));\n\treturn serviceURL.host;\n}\nlet SERVICE_PORT = function (arg){\n\tvar processorHandler = this; // to make this always works, do not use arrow functions to define your\n\tlet serviceURL = new URL(processorHandler.processors.ENV(arg));\n\treturn serviceURL.port;\n}\n\nProcessor.setProcessor(SERVICE_HOST);\nProcessor.setProcessor(SERVICE_PORT);\n```\n\nEntonces solo necesita establecer su variable de entorno SERVICE_URL en su shell\n\nLo siguiente es para los sistemas operativos de Unix/Linux :\n```shell\nexport SERVICE_URL=\"https://example.com:443/path-to-a-resource/\"\n```\n\nY su configuración se cargará dinámicamente de esta manera:\n\n```json\n{\n\t\"serviceURL\":\"https://example.com:443/path-to-a-resource/\",\n\t\"host\":\"example.com\",\n\t\"port\":\"443\"\n}\n```\n\nY consigue tus valores correspondientes en **CONFIG.get(value)**\n\n### waitUntil\nWaitUntil es un ayudante solo en caso de que estés en problemas tratando de correr el código antes de que la condición sea real. El código dentro del waitUntil sera ejecutado una vez.\n\nNOTA: Esto es útil en algunos casos pero no es recomendado para uso excesivo.\n\n#### Uso:\n```javascript\nwaitUntil(()=\u003e{\n  // the code that will be executed after the condition is true\n},()=\u003e{return condition;});\n// where condition is what I want to wait for\n```\n\n#### Ejemplo:\n```javascript\nlet someVar = 0;\nwaitUntil(()=\u003e{\n  console.log('someVar is present');\n},()=\u003e{return typeof someVar != 'undefined';});\n// where condition is what I want to wait for\n```\n\n\n### Package\nDefine el paquete de QCObjects y regrésalo.\n\n#### Uso:\n```javascript\nPackage('packageName',[packageContent]);\n```\nDonde packageContent es una gama de clases de QCObjects. Si solo pasas el packageName param conseguirás el contenido declarado anteriormente.\n\n\n#### Ejemplo (1):\n```javascript\n'use strict';\nPackage('org.quickcorp.main',[\n  Class('Main',InheritClass,{\n    propertyName1:'propertyValue1',\n  }),\n  Class('MyCustomClass',InheritClass,{\n    propertyName2:'propertyValue2',\n  }),\n]);\n```\n#### Ejemplo (2):\n```javascript\nlet mainPackage = Package('org.quickcorp.main'); // this will return the previously declared content of package 'org.quickcorp.main'\n// mainPackage[0] will be the Main class definition.\n// This is useful for code introspection\n```\n\nLa técnica de carga de paquetes presente en QCObjects esta basada en una promesa y orientada al alcance. Puedes preguntar si un paquete fue cargado simplemente llamando la función Packege() pasando el nombre del paquete a un argumento.\n\n\n### Import\nImporta un paquete desde otro archivo JS.\n\n#### Uso:\n```javascript\nImport (packagename,[ready],[external]);\n```\nDonde el packagename es el nombre del paquete, listo es una función que podrá ser ejecutada después de que el paquete es cargado y el externo es un valor bolean que indica si el archivo JS esta en el mismo origen o esta desde otro recurso externo.\n\n#### Ejemplo (1):\n```javascript\nImport('org.quickcorp.main');\n```\nEl código anterior intentara importar un archivo JS llamado 'org.quickcorp.main.js' desde un camino especifico en el valor de ajuste  **relativeImportPath** presente en tu **CONFIG**. Dentro del archivo tienes que definir el paquete mediante el uso del paquete ('org.quickcorp.main',[Class1, Class2...])\n\n#### Ejemplo (2):\n```javascript\nImport('org.quickcorp.main',function (){\n  console.log('remote import is loaded');\n},true);\n```\nEl código anterior esta vez esta tratando de cargar en el mismo paquete usando el camino externo mediante el **remoteImportsPath** ajustes presentes en tu **CONFIG**\n\nNOTA: En los dos ejemplos anteriores no necesitas usar o especificar la extensión \".js\". Esto esta usado por defecto y no puede ser cambiado por razones de seguridad.\n\n### Export\nPon un símbolo(barra o función) en el alcance global.\n\n#### Uso:\n\n```javascript\nExport('name of symbol');\n```\n\n#### Ejemplo:\n```javascript\n(()=\u003e{\n  // this is local scope\n  let someFunction = (someLocalParam)=\u003e{\n    console.log(someLocalParam);\n  };\n  Export(someFunction); // now, someFunction is in the top level scope.\n})();\n\n\n// this is the top level scope\nsomeFunction('this works');\n```\n\n### Cast\n\nUsa el método Cast de cualquier elemento DOM para obtener las propiedades de otro tipo de objeto. Esto es útil para trasformar un tipo objeto a otro otorgándole mas flexibilidad a tu código.\n\n#### Uso:\n\n```javascript\nlet resultObject = [element or QCObjects type].Cast(objectToCastFrom);\n```\n\nDonde objectToCastFrom es un objeto para obtener propiedades desde y poner el objeto resultante regresado por el cast.\n#### Ejemplo:\n\n```javascript\nClass('MyOwnClass',{\n  prop1:'1',\n  prop2:2\n});\n\nlet obj = document.createElement('div').Cast(MyOwnClass);\n```\n\nEl código anterior creara un objeto DOM y lo emitirá a MyOwnClass. Gracias a que MyOwnClass es un tipo clase de QCObject el objeto ahora tendrá propiedades prop1 y prop2 y ahora sera una instancia de objeto QCObject con una propiedad del cuerpo que es un elemento div.\n\n### Tag\nEtiquetar es una función útil para seleccionar cualquier elemento DOM usando selectores. Etiquetar siempre regresa a la lista de elementos que puedas mapear, ordenar y filtrar como cualquier otra lista.\n\n#### Uso:\n\n```javascript\nvar listOfElements = Tag(selector);\n```\n\nDonde el selector es un DOM selector de respuestas.\n\n#### Ejemplo:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n    \t\u003ctitle\u003eDemo\u003c/title\u003e\n    \t\u003cscript type=\"text/javascript\" src=\"https://qcobjects.dev/QCObjects.js\"\u003e\u003c/script\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n    \u003cdiv class=\"myselector\"\u003e\n    \u003cp\u003eHello world\u003c/p\u003e\n    \u003c/div\u003e\n    \u003cscript\u003e\n    Ready(()=\u003e{\n      Tag('.myselector \u003e p').map((element)=\u003e{\n        element.innerHTML = 'Hello world! How are you?';\n      });\n    });\n    \u003c/script\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nEn el código anterior el elemento párrafo fue creado dentro de un div con una clase css llamada myselector mediante html y luego es modificada dinámicamente usando la función etiqueta de QCObject. Si estas familiarizado con un framework selector query te encantara este.\n\n### Ready\nAsigna una función para correr después de que todo esta hecho mediante QCObject y después del evento window.onload. Úsalo para prevenir un error de objeto DOM 'indefinido'.\n\n#### Uso:\n```javascript\nReady(()=\u003e{\n  // My init code here!\n});\n```\nTenga en cuenta que si define los componentes dinámicos mediante el uso de una etiqueta \"componente\" en HTML, el contenido dinámico no activara eventos listos. Para atrapar el código cada vez que se carga un componente dinámico usa un método decontrolado hecho en su lugar.\n\nUsaras implementación lista principalmente cuando quieras implementar QCObjects en conjunto con otro framework que lo necesite.\n\n### Component Class\nUn tipo clase de QCObject por componentes.\n\n#### Propiedades\n\n**[Component].domain**\nRegresa una cadena con el dominio de tu aplicación. Se establece automáticamente por QCObjects al momento de cargar.\n\n**[Component].basePath**\nRegresa una cadena con un camino url base de tu aplicación. Se establece automáticamente por QCObjects al momento de cargar.\n\nNOTA: Si quieres cambiar los componentes con base en un camino, tienes que usar _CONFIG.set('componentsBasePath','new path relative to the domain')_ en tu unidad de código.\n\n**[Component].templateURI**\nEs una cadena representando un componente plantilla URI relativo al dominio. Cuando este listo, el componente sera cargado a la plantilla y lo agregara al contenido interno dentro del cuerpo childs como parte del DOM. Para establecer esta propiedad es recomendado usar la función ayudante ComponentURI.\n\n**[Component].tplsource**\nEs la cadena representando a la fuente donde el template sera cargado. Puede ser \"default\" o \"none\". El valor \"default\" le dirá a QCOBject que cargue el template desde el contenido templateURI. El valor \"none\" le dirá a QCObject que no cargue el template desde ningún lado.\n\n**[Component].url**\nEs una cadena representando una url completa de un componente. Es automáticamente establecido por QCObjects cuando un componente es instanciado.\n\n**[Component].name**\nEs una cadena que representa el nombre de un componente. El nombre de un componente puede ser cualquier valor alphanumerico que identifique un tipo de componente. Sera internamente utilizado mediante ComponentURI para construir un tempalte URI normalizado.\n\n**[Component].method**\nEs una cadena que representa a un método HTTP o HTTPS. Por defecto cada componente esta configurad para usar el método \"GET\". En la mayoría de los casos no necesitas cambiar esta propiedad.\n\n**[Component].data**\nEs un objeto que representa los datos del componente. Cuando QCObject carga un template este conseguirá cada propiedad de los datos y la atará al nivel de template representado por la misma propiedad dentro del contenido del template entre los brackets dobles, ejemplo:  (example: {{prop1}} in the template content will represent data.prop1 in the component instance).\nNOTA: Para refrescar los enlaces de datos para reconstruir el component (mira el uso de [Component].rebuild() para mas detalles ).\n\n**[Component].reload**\nEs un valor boolean el que dice cuando qcobjects es obligado a recargar el contenido de un componente en el template o no. Si el valor es cierto, el contenido del template sera remplazado por los actuales hijos DOM del elemento cuerpo. Si este valor es falso, el contenido del template sera añadido después de los hijos del componente cuerpo.\n\n**[Component].cached**\nEs un valor booleado el que le dice a QCObject si el componente necesita ser atrapado o no. Cuando el componente es atrapado, el contenido del template es cargado desde templateURI sera cargado una sola vez. Puedes configurar esta propiedad incluso como una propiedad estática de un componente de clase para configurarlo como un valor predeterminado para cada siguiente componente instancia de objeto o configurarlo de manera individual el valor de la propiedad en cada definición de componente. En un mundo donde el desempeño cuenta, para darle mas flexibilidad al comportamiento del cache es necesitado mas que nunca.\n\n**[Component].routingWay**\nRegresa una cadena representando la forma de enrutamiento. Un valor puede ser \"hash\", \"pathname\" o \"search\".\nNOTA: Para cambiar el routingWay de cada componente es recomendado usar CONFIG.set('routingWay','value of a valid routing way')en tu unidad de código.\n\n**[Component].validRoutingWays**\nRegresa a la lista que representa la forma de enrutamiento. QCObject usa esto internamente para validar el routingWay el cual usa para construir los enrutamientos de componente.\n\n**[Component].routingNodes**\nRegresa al objeto NodeList representando la lista de nodes que fueron cargados por el creador de enrutamientos.\n\n**[Component].routings**\nRegresa a la lista con los componentes complicados cuando el componente fue instanciado.\n\n**[Component].routingPath**\nRegresa una cadena que representa el camino del enrutamiento actual.\n\n**[Component].routingSelected**\nRegresa un objeto que representa el componente de enrutamiento actual.\n\n**[Component].subcomponents**\nRegresa a la lista de componentes que son childs de las instancias de componentes.\n\n**[Component].body**\nEs un elemento DOM que representa el cuerpo del componente\nNOTA:Cada vez que un cuerpo es configurado, sera activado el generador de rutas para este componente.\n\n#### Métodos\n**[Component].set('prop',value)**\nEstablece un valor para una propiedad de componente.\n\n**[Component].get('prop')**\nDevuelve el valor de una propiedad componente\n\n**[Component].rebuild()**\nReconstruye un componente. Forzará una llamada para el cargador de componentes con este componente cuando sea necesario.\n\n**[Component].Cast(ClassName or ComponentClassName)**\nDevuelve el reparto de una definición de componente en otra. Esto es útil para combinar dinámicamente definiciones de componentes.\n\n**[Component].route()**\nFuerza al generador de rutas de componentes a recargar las rutas del componente. Esto resultara en una reconstrucción de llamada cuando sea necesario.\n\n**[Component].fullscreen()**\nPone el componente en modo de pantalla completa.\n\n**[Component].closefullscreen()**\nCierra el modo de pantalla completa.\n\n**[Component].css(css object)**\nEstablece las propiedades del css para el componente.\n\n**[Component].append(component or QCObjects object)**\nAgrega un componente como hijo del cuerpo del componente actual\n\n**[Component].attachIn(selector)**\nAdjunta un cuerpo de componente actual a cualquier elemento en el selector dado.\n\n### Tag HTML Component\nUna etiqueta HTML es una representación de una instancia de componente. Cada declaración de una etiqueta `\u003ccomponent\u003e\u003c/component\u003e`generara una instancia relacionada con un componente QCObjects. Mientras una etiqueta de componente no es una instancia por si misma, incluso puedes definir algunas propiedades de instancia configurando el atributo de etiqueta relacionado cuando esté disponible.\n\n#### Atributos disponibles\nA continuación se muestra una lista de los atributos disponibles para una etiqueta de componente\n\n##### El atributo name\n**`\u003ccomponent name\u003e`**\nEstablece el nombre de la instancia de componente relacionada creada por QCObjects.\n\n###### Uso:\n```html\n\u003ccomponent name=\"name_of_component\"\u003e\u003c/component\u003e\n```\n\n###### Ejemplo:\n```html\n\u003c!-- index.html --\u003e\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n    \t\u003ctitle\u003eDemo\u003c/title\u003e\n    \t\u003cscript type=\"text/javascript\" src=\"https://qcobjects.dev/QCObjects.js\"\u003e\u003c/script\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n      \u003c!-- this will load the contents of ./templates/main[.tplextension] file --\u003e\n      \u003ccomponent name=\"main\"\u003e\u003c/component\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n##### El atributo cached\n**`\u003ccomponent cached\u003e`**\nEstablece la propiedad en caché si la instancia relacionada de un componente.\n\nNOTA: Solo se puede establecer un valor de \"verdadero\" para indicar a QCObjects que el contenido de la plantilla del componente debe almacenarse en caché. Cualquier otro valor sera interpretado como falso.\n\n ###### Uso:\n```html\n\u003ccomponent name=\"name_of_component\" cached=\"true\"\u003e\u003c/component\u003e\n```\n\n##### La declaración de la propiedad data\n **`\u003ccomponent data-property1 data-property2 ...\u003e`**\nConfigura un valor estatico de las propiedades de los datos en una instancia de componente.\n\nNOTA: La declaración de la etiqueta de propiedad de datos se pensó con el propósito de dar una forma simple de hacer mocking de un componente dinámico con asignaciones de Template. No lo uses pensando que es una forma bidireccional de datos. Mientras puedas tener un comportamiento de forma bidireccional accediendo a los objetos de datos desde una instancia de componente, no es lo mismo que la etiqueta de componente. La declaración de propiedad de datos en una etiqueta de componente es solo una forma de unión de datos debido a los componentes de arquitectura de árbol.\n\n##### El atributo controllerClass\n**`\u003ccomponent controllerClass\u003e`**\nDefine un controlador de clase personalizado desde una instancia de componente.\n\n###### Uso:\n```html\n\u003ccomponent name=\"name_of_component\" controllerClass=\"ControllerClassName\"\u003e\u003c/component\u003e\n```\n\n\n##### El atributo viewClass\n **`\u003ccomponent viewClass\u003e`**\nDefine una vista de clase personalizada para la instancia del componente\n\n###### Uso:\n```html\n\u003ccomponent name=\"name_of_component\" viewClass=\"ViewClassName\"\u003e\u003c/component\u003e\n```\n\n\n##### El atributo componentClass\n**`\u003ccomponent componentClass\u003e`**\nDefine un componente de clase personalizado para la instancia de un componente.\n\n###### Uso:\n```html\n\u003ccomponent name=\"name_of_component\" componentClass=\"ComponentClassName\"\u003e\u003c/component\u003e\n```\n\n##### El atributo effecClass\n**`\u003ccomponent effectClass\u003e`**\nDefine un efecto de clase personalizado para la instancia del componente\n\n###### Uso:\n```html\n\u003ccomponent name=\"name_of_component\" effectClass=\"EffectClassName\"\u003e\u003c/component\u003e\n```\n\n##### El atributo template-source\n**`\u003ccomponent template-source\u003e`**\nEstablece el tplsource de una propiedad relacionada con una instancia de un componente Posiblemente los valores son \"none\" o\"default\".\n\n###### Uso:\n```html\n\u003ccomponent name=\"name_of_component\" template-source=\"none\"\u003e\u003c/component\u003e\n```\n\n##### El atributo tplextension\n**`\u003ccomponent tplextension\u003e`**\nEstablece la propiedad de tplextension relacionada con una instancia de un componente. Posibles valores son cualquier archivo de extensión. El valor por defecto es \"html\"\n\n###### Uso:\n```html\n\u003ccomponent name=\"name_of_component\" tplextension=\"tpl.html\"\u003e\u003c/component\u003e\n```\n\n\n#### ComponentURI\nEs una función ayudante la que te deja definir el templateURI por un componente en una forma normalizada\n\n##### Ejemplo:\n```javascript\nvar templateURI = ComponentURI({\n  'COMPONENTS_BASE_PATH':CONFIG.get('componentsBasePath'),\n  'COMPONENT_NAME':'main',\n  'TPLEXTENSION':\"tpl.html\",\n  'TPL_SOURCE':\"default\"\n});\n\nconsole.log(templateURI); // this will show something like \"templates/components/main.tpl.html\" depending on your CONFIG settings\n```\n\n\n#### componentLoader\nCarga una instancia de componente en un nivel bajo y agrega el tempalte del componente a el cuerpo del componente. En la mayoría de los casos no necesitara llamar al componentLoader con el fin de cargar un componente. Esto es automáticamente llamado por QCObjects cuando sea necesario. ComponentLoader regresa una promesa que es resuelta cuando el componente se ha cargado y rechazado cuando el componente fallo.\n\n##### Uso:\n```javascript\n [Promise] componentLoader(componentInstance,load_async)\n```\n\nDonde componentInstance es una instancia de componente creada por _`New(ComponentDefinitionClass)`_\n\n##### Ejemplo:\n```javascript\ncomponentLoader(componentInstance,load_async).then(\n  (successStandardResponse)=\u003e{\n    // component load successful\n    var request = successStandardResponse.request;\n    var component = successStandardResponse.component;\n  },(failStandardResponse)=\u003e{\n    // component load failed\n    var component = failStandardResponse.component;\n  });\n```\n\n\n#### buildComponents\nReconstruye cada componente que sea un elemento child del elemento DOM, quien posee el método. En la mayoría de los casos no necesitaras llamar a builcomponents con la intención de construir o reconstruir todos los componentes del DOM. Esto es automáticamente llamado por QCObjects cuando es necesario.\n\n\n##### Uso:\n```javascript\n[element].buildComponents()\n```\n\n##### Ejemplo:\n```javascript\ndocument.buildComponents()\n```\n\n\n### Controller\nUna clase QCObjects built-in para definir un contorlador.\n\n### View\nUna vista QCObjects built in para definir una vista.\n\n### VO\nUna clase QCObjects built-in para definir un valor de objeto.\n\n\n### Service\nUn tipo clase QCObjects para servicio.\n\n\n#### Propiedades\n\n**[Service].domain**\nRegresa a una cadena que domina tu aplicación.Es automáticamente configurado por QCObjects a la hora de carga.\n\n**[Service].basePath**\nRegresa a la cadena con un camino base url para tu aplicación. Es automáticamente configurado por QCObjects a la hora de carga.\n\n**[Service].url**\nUna cadena representa el url completo del servicio. Puede ser absoluto o relativo para el basepath cuando es aplicado. Puede ser también un url externo.\n\nNOTA: Para cargar un servicio de un recurso externo necesitaras expecificar el parámetro al verdadero usando serviceLoader.\n\n**[Service].name**\nUna cadena representando el nombre de un componente. El nombre de un servicio puede ser de cualquier valor alphanumerico que identifique la instancia del servicio. No es una identificación única, sino solo un nombre descriptivo.\n\n**[Service].method**\nUna cadena representando a un metodo HTTP o a HTTPS. Los posibles valores son :\"GET\", \"POST\", \"PUT\", ... cualquier otro sera aceptado mediante servicios de llamadas REST.\n\n**[Service].data**\nEs un objeto representando al servicio de datos. Cuando QCObjects carga el servicio recibe una respuesta y lo interpreta como un template. Así que una vez la respuesta del servicio es obtenida, Tomara cualquier propiedad de un objeto de datos y lo atara a una etiqueta template representando la misma propiedad dentro del contenido entre los brackets dobles(Ejemplo: {{prop1}}en el contenido de la plantilla se representará data.prop1 en la instancia de servicio).\n\n**[Service].cached**\nEs un servicio boolean el que le dice a QCObjects si la respuesta necesita ser cacheada o no. Cuando el servicio es cacheado el contenido plantilla cargara desde el servicio url que sera cargado de una vez. Necesitas configurar el valor falso para cada instancia de servicio defines para asegurar la carga del servicio desde el recurso pero, no del almacenamiento caché.\n\n#### Métodos\n**[Service].set('prop',value)**\nEstablece un valor para una propiedad de servicio.\n\n**[Service].get('prop')**\nDevuelve el valor de una propiedad de servicio\n\n\n### serviceLoader\nCarga una instancia de servicio y regresa a la promesa que es resuelta cuando los servicios han respondido exitosamente a la carga y rechazados cuando falla la respuesta de carga.\n\n#### Uso:\n```javascript\n[Promise] serviceLoader(serviceInstance)\n```\n\n#### Ejemplo:\n```javascript\nClass('MyTestService',Service,{\n    name:'myservice',\n    external:true,\n    cached:false,\n    method:'GET',\n    headers:{'Content-Type':'application/json'},\n    url:'https://api.github.com/orgs/QuickCorp/repos',\n    withCredentials:false,\n    _new_:()=\u003e{\n      // service instantiated\n    },\n    done:()=\u003e{\n      // service loaded\n    }\n});\nvar service = serviceLoader(New(MyTestService,{\n  data:{param1:1}\n})).then(\n  (successfulResponse)=\u003e{\n    // This will show the service response as a plain text\n    console.log(successfulResponse.service.template);\n  },\n  (failedResponse)=\u003e{\n\n  });\n```\n\n\n### JSONService\nEs la definición Buil-in para un servicio de clase JSON\n\n#### Propiedades\n\n**[JSONService].domain**\nRegresa una cadena con la que domina tu aplicación. Es automáticamente configurada por QCObjects a la hora de carga.\n\n**[JSONService].basePath**\nRegresa una cadena con camino url base de tu aplicación. Es automáticamente configurada por QCObjects a la hora de carga.\n\n**[JSONService].url**\nUna cadena completa representando a todo el servicio url. Puede ser absoluto o relativo al basePath cuando es aplicado. Puede ser tambien un url externo.\n\nNOTA: Para cargar un srvicio de un recurso interno necesitas especificar el parametro externo para verdaderamente usar el serviceLoader.\n\n**[JSONService].name**\nEs una cadena representando un componente. El nombre del servicio puede ser cualquier valor alphanumerico que identifique el servicio de instancia. No es una identificación única, sino solo un nombre descriptivo.\n\n**[JSONService].method**\nEs una cadena representando el metodo HTTP o HTTPS. Los posible valores son:\"GET\", \"POST\", \"PUT\", ... Cualquier otro sera aceptado mediante servicios de llamadas REST.\n\n**[JSONService].data**\nEs un objeto representando al servicio de datos. Cuando QCObjects carga el servicio recibe una respuesta y lo interpreta como un template. Así que una vez la respuesta del servicio es obtenida, Tomara cualquier propiedad de un objeto de datos y lo atara a una etiqueta template representando la misma propiedad dentro del contenido entre los brackets dobles(Ejemplo: {{prop1}}en el contenido de la plantilla se representará data.prop1 en la instancia de servicio).\n\n\n**[JSONService].cached**\nEs un servicio boolean el que le dice a QCObjects si la respuesta necesita ser cacheada o no. Cuando el servicio es cacheado el contenido plantilla cargara desde el servicio url que sera cargado solo una vez. Necesitas configurar el valor falso para cada instancia de servicio defines para asegurar la carga del servicio desde el recurso pero, no del almacenamiento caché.\n#### Métodos\n**[JSONService].set('prop',value)**\nConfigura el Valor para una propiedad de servicio.\n\n**[JSONService].get('prop')**\nRegresa el valor de una propiedad de servicio.\n\n#### Ejemplo:\n```javascript\nClass('MyTestJSONService',JSONService,{\n    name:'myJSONservice',\n    external:true,\n    cached:false,\n    method:'GET',\n    withCredentials:false,\n    url:'https://api.github.com/orgs/QuickCorp/repos',\n    _new_:function (){\n      // service instantiated\n      delete this.headers.charset; // do not send the charset header\n    },\n    done:function (result){\n      _super_('JSONService','done').call(this,result);\n    }\n});\nvar service = serviceLoader(New(MyTestJSONService,{\n  data:{param1:1}\n})).then(\n  (successfulResponse)=\u003e{\n    // This will show the service response as a JSON object\n    console.log(successfulResponse.service.JSONresponse);\n  },\n  (failedResponse)=\u003e{\n\n  });\n```\n\n### ConfigService\nEs una definicion de clase Buil-in que carga los ajustes CONFIG desde un archivo config.json\n\n#### Ejemplo:\n```javascript\n// To set the config.json file relative url\nConfigService.configFileName='config.json'; // it is done by default\nCONFIG.set('useConfigService',true); // using config.json for custom settings config\n```\n\n\n### SourceJS\nUsa SourseJS como una clase estática que esta ayudándote a cargar dependencias JS externas. Esto es comúnmente usado para cargar librerías externas y que no siga el paquete sintaxis de QCObjet.\n\n#### Ejemplo:\n```javascript\nClass(\"MyNewController\",Controller,{\n\t_new_:function (){\n\t\tvar controller = this;\n\t\tcontroller.dependencies.push(\n\t\t\tNew(SourceJS,{\n\t\t\t\texternal:false,\n\t\t\t\turl:'doc/js/my-js-resource.js',\n\t\t\t\tdone:function(){\n\t\t\t\t\tlogger.debug(\"Dependency loaded\")\n\t\t\t\t}})\n\t\t\t);\n\t}\n})\n```\n\n### SourceCSS\n\nUna clase estatica que es usada para cargar recursos CSS externos.\n\n```javascript\nClass(\"MyNewController\",Controller,{\n\tdependencies:[],\n\tdone (){\n\t\tthis.dependencies.push(New(SourceCSS,{\n\t\t\texternal:false,\n\t\t\turl:CONFIG.get('basePath')+'css/my-css-resource.css'\n\t\t}));\n\t}\n});\n```\n\n### Effect\n\n**Effect** es una super clase para definir los efectos.\n\n#### Ejemplo:\n\n```javascript\nClass('CustomFade',Effect,{\n\tduration:500, // milliseconds of duration\n\tapply: function (){\n\t\t// Necesitas la siguiente línea para crear un efecto Fade en runtime\n\t\t_super_('Fade','apply').apply(this,arguments);\n\t}\n})\n```\n\n\n### Timer\n\n**Timer** es una implementación especial de **requestAnimationFrame** para emular la creación de instancias de hilo, así puedes manejar runtime paralell processing en una manera un poquito más eficiente.\n\nNOTA: Como depende de la dispoinibilidad de requestAnimationFrame solo funciona en browsers modernos.\n\n#### Ejemplo:\n\n```javascript\nTimer.thread({\n\t\tduration:300, // duración en milisegundos\n\t\ttiming(timeFraction,elapsed){\n\t\t\treturn timeFraction; // puedes cambiar esta línea para devolver una función customizada para timing\n\t\t},\n\t\tintervalInterceptor(progress){\n\t\t\tif (progress\u003e=100){\n\t\t\t\t// haz lo que quieras aquí\n\t\t\t}\n\t\t}\n});\n```\n\n## Funciones de lista y matemáticas\n\n### ArrayList\n\nUna definición de clase usada para manejar listas\n\n```javascript\nlet myvar = New(ArrayList,[1,2,3]);\n```\n\n### ArrayCollection\n\nUna definición extendida para manejo avanzado de colecciones\n\n```javascript\nlet collection = New(ArrayCollection, {source:[0,1,2]});\n```\n\n### [ArrayList or Array].unique\n\nFiltra un objeto Array o ArrayList para obtener solo elementos únicos.\nNOTA: Solo filtra una secuencia de valor único.\n\n```javascript\nlet my_unique_list = [0,1,2,1,2].unique()\n// will result in: my_unique_list = [ 0, 1, 2 ]\n```\n\n### [ArrayList or Array].table\n\nEsto esta destinado para solo el uso de shell script. Muestra una tabla de valores en una lista.\n\n```javsascript\n[\"a\",\"b\",\"c\",\"d\"].table()\n// it will show\n┌─────────┬────────┐\n│ (index) │ Values │\n├─────────┼────────┤\n│    0    │  'a'   │\n│    1    │  'b'   │\n│    2    │  'c'   │\n│    3    │  'd'   │\n└─────────┴────────┘\n```\n\n### [ArrayList or Array].sort\n\nOrdena los elementos del array o lista.\n\n```javascript\nlet my_sorted_array = [3,3,4,0,2,1].sort()\n// my_sorted_array = [ 0, 1, 2, 3, 3, 4 ]\n```\n\n```javascript\nlet my_sorted_list = New(ArrayList,{source:[3,3,4,0,2,1]}).source.sort()\n// my_sorted_list = [ 0, 1, 2, 3, 3, 4 ]\n```\n\n\n### [ArrayList or Array].sortBy\n\nOrdena una lista de objetos por un valor de propiedad.\n\n\n```javascript\nlet my_ordered_list = [\n\t\t\t\t\t\t\t\t\t\t\t\t{\"b\":1,\"a\":2},\n\t\t\t\t\t\t\t\t\t\t\t\t{\"b\":2,\"a\":1},\n\t\t\t\t\t\t\t\t\t\t\t\t{\"b\":3,\"a\":3},\n\t\t\t\t\t\t\t\t\t\t\t].sortBy(\"a\")\n// it will result in\n[\n\t{ b: 2, a: 1 },\n\t{ b: 1, a: 2 },\n\t{ b: 3, a: 3 }\n]\n```\n\n### [ArrayList or Array].matrix\n\nGenera una matriz en una dimensión.\n\n#### Uso\n**[].matrix (length, [value])** Donde **length** es un numero de elementos y el **value** opcional es un valor en cada elemento, puede ser cualquier valor de cualquier tipo.\n\n```javascript\nlet matrix = Array.matrix(10);\n// matrix = [\n  0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0\n]\n```\n\n```javascript\nlet matrix = ArrayList.matrix(10,1);\n// matrix = [\n  1, 1, 1, 1, 1,\n  1, 1, 1, 1, 1\n]\n```\n\n```javascript\nlet a = 1, b = 2;\nlet c = ArrayList.matrix(10,{a,b})\n// c = [\n { a: 1, b: 2 },\n { a: 1, b: 2 },\n { a: 1, b: 2 },\n { a: 1, b: 2 },\n { a: 1, b: 2 },\n { a: 1, b: 2 },\n { a: 1, b: 2 },\n { a: 1, b: 2 },\n { a: 1, b: 2 },\n { a: 1, b: 2 }\n]\n```\n\n\n### [ArrayList or Array].matrix2d\n\nCrea una matriz 2D.\n\n```javsascript\nlet matrix2d = ArrayList.matrix2d(2,1);\n// [ [ 1, 1 ], [ 1, 1 ] ]\n```\n\n### [ArrayList or Array].matrix3d\n\nCrea una matriz 3D\n\n```javascript\nlet matrix3d = ArrayList.matrix3d(3,\"a\");\n// it will result in a 3x3 matrix with the value \"a\" on every element\n[\n  [ [ 'a', 'a', 'a' ], [ 'a', 'a', 'a' ], [ 'a', 'a', 'a' ] ],\n  [ [ 'a', 'a', 'a' ], [ 'a', 'a', 'a' ], [ 'a', 'a', 'a' ] ],\n  [ [ 'a', 'a', 'a' ], [ 'a', 'a', 'a' ], [ 'a', 'a', 'a' ] ]\n]\n```\n\n### range\n\nA Python le gusta la función de crear una lista de rango. Puedes usarla en conjunto con ArrayList.matrix, ArrayList.matrix2d y ArrayList.matrix3d para generar rangos complejos de matriz.\n\n#### Uso\n\nrango (longitud) o rango (initialIndex, finalIndex)\nrange () sin ningún parámetro devuelve una lista vacía\nrange (0) devuelve una lista con un elemento con valor 0\n\n\n```javascript\nlogger.debugEnabled=true;\n\nfor (var i in range(10)){\n\t(!isNaN(i) \u0026\u0026 logger.debug(i))\n}\n\n// the above code will show\n[DEBUG] 0\n[DEBUG] 1\n[DEBUG] 2\n[DEBUG] 3\n[DEBUG] 4\n[DEBUG] 5\n[DEBUG] 6\n[DEBUG] 7\n[DEBUG] 8\n[DEBUG] 9\n[DEBUG] 10\n```\n\n```javascript\nlogger.debugEnabled=true;\n\n// same result will be obtained iterating the range first\nfor (var i in {...range(10)}){\n\tlogger.debug(i)\n}\n\n// the above code will show\n[DEBUG] 0\n[DEBUG] 1\n[DEBUG] 2\n[DEBUG] 3\n[DEBUG] 4\n[DEBUG] 5\n[DEBUG] 6\n[DEBUG] 7\n[DEBUG] 8\n[DEBUG] 9\n[DEBUG] 10\n```\n\n```javascript\n// a bit shorter syntax for the same result\nrange(10).map(n=\u003elogger.debug(n))\n```\n\n```javascript\nlet normalizedMatrix = ArrayList.matrix(3,range(2));\n// normalizedMatrix = [ [ 0, 1, 2 ], [ 0, 1, 2 ], [ 0, 1, 2 ] ]\n```\n\n```javascript\nlet my3dmatrix = ArrayList.matrix3d(3,range(0,1));\n// my3dmatrix will be\n[\n  [\n    [ [0, 1], [0, 1], [0, 1] ],\n    [ [0, 1], [0, 1], [0, 1] ],\n    [ [0, 1], [0, 1], [0, 1] ]\n  ],\n  [\n    [ [0, 1], [0, 1], [0, 1] ],\n    [ [0, 1], [0, 1], [0, 1] ],\n    [ [0, 1], [0, 1], [0, 1] ]\n  ],\n  [\n    [ [0, 1], [0, 1], [0, 1] ],\n    [ [0, 1], [0, 1], [0, 1] ],\n    [ [0, 1], [0, 1], [0, 1] ]\n  ]\n]\n```\n### Array.sum\n\nSuma los elementos de una matriz.\n\n```javascript\nlet s = [1,2,3].sum()\n// s = 6\n```\n\n### Array.avg\n\nCalcula el valor promedio de los elementos en el Array\n\n```javascript\nlet average = [10,5].avg()\n// average = 7.5\n```\n\n### Array.min\n\nDevuelve el valor mínimo de los elementos de un Array.\n\n```javascript\nlet minValue = [1,2,3].min()\n// minValue = 1\n```\n\n\n### Array.max\n\nDevuelve el valor máximo de los elementos de unArray\n\n```javascript\nlet maxValue = [1,2,3].max()\n// maxValue = 3\n```\n\n## SDK\n\n### SDK Components\n\n#### org.quickcorp.components.ShadowedComponent\n\nLa Clase **ShadowedComponent** es un componente personalizado diseñado para permitirte crear un componente usando el Shadow DOM de un buscador. Lee mas sobre los componentes Shadow en [Este articulo en Hackernoon]\n (https://www.hackernoon.com/shadowed-components-and-qcobjects-kd703yld).\n\n##### Uso:\n\n```html\n\u003ccomponent componentClass=\"ShadowedComponent\"\u003e\u003c/component\u003e\n```\n\n#### org.quickcorp.components.FormField\n\n**FormField** es una clase par los componentes personalizados**QCObjects** que te permiten que le permite inyectar un comportamiento genérico de campo de formulario a sus componentes. Tiene una característica inversa data-binding para detectar valores de los campos DOM dentro de tu formulario y asignarlos a los valores de datos de tu componente. De esta forma no perderás el desempeño creando un data binig bidireccional a la antigua basado en observables. Para implementar este comportamiento avanzado, necesitas hacer lo siguiente:\n\n1.- Asigna un atributo **data-field** a la etiqueta DOM dentro del cuerpo del componente con el nombre del campo correspondiente en tu objeto de datos.\n\n2.- A tu **component tag**, asígnale **FormField** en el atributo **componentClass**.\n\n3.- Para recuperar los datos del formulario dentro de tu componente solo tienen que usar el componentInstance.data .  Cada propiedad del objeto componentInstance.data sera unido por los eventos bindig con ls propiedades del valor en cada objeto DOM del formulario que ha sido asignado al data-field.\n\n##### Uso:\n\n```html\n\u003c!-- Where you place the component --\u003e\n\u003ccomponent name=\"myform\" componentClass=\"FormField\"\u003e\u003c/component\u003e\n```\n\n```html\n\u003c!-- template: myform.tpl.html --\u003e\n\u003clabel for=\"email\"\u003e\u003cb\u003eEmail\u003c/b\u003e\u003c/label\u003e\n\u003cinput data-field=\"email\" type=\"email\" placeholder=\"Enter Email\" name=\"email\" required\u003e\n\n\u003clabel for=\"psw\"\u003e\u003cb\u003ePassword\u003c/b\u003e\u003c/label\u003e\n\u003cinput data-field=\"name\" type=\"text\" placeholder=\"Enter Your Name\" name=\"name\" required\u003e\n```\n\n**data-field=\"name\"** será emparejado con  **this.data.name** dentro de la clase de componente y se actualizará cada vez que se active un evento de enlace de datos. Lo mismo pasa con **data-field=\"email\"** y así.\n\n##### FormField.executeBindings():\n\n El método **executeBindings** del componente FormField donde encontraras los valores de atributo **data-field** y emparejaras con ellos los correspondientes archivos **data** en una instancia de componente.\n\n##### Data Binding Event Change:\n\nDentro del cuerpo de su componente, cuando es un componente **FormField** cada vez que el DOM envía un evento de \"cambio\", activará el método executeBindings de su componente.\n\n##### Data Binding Event Blur:\n\nDentro del cuerpo de su componente, cuando es un componente **FormField** cada vez que el DOM envía un evento \"Blur\", activará el método executeBindings de su componente.\n\n##### Data Binding Event Focus:\n\nDentro del cuerpo de su componente, cuando es un componente**FormField** cada vez que el DOM envía un evento \"Focus\", activará el método executeBindings de su componente.\n##### Data Binding Event Keydown:\n\nDentro del cuerpo de su componente, cuando es un componente **FormField** cada vez que el DOM envía un evento \"Keydown\", activará el método executeBindings de su componente.\n\n#### org.quickcorp.components.ButtonField\n\n**ButtonField** es una subdefinición de **FormField** que es comunmete usando para casi el mismo proposito del FormField.La principal diferencia entre ButtonField y FormField es que ButtonField tiene un elemento DOM ** `` `\u003cbutton\u003e` `` ** como el cuerpo del componente por defecto. Y FormField no tiene un cuerpo predefinido.\n\n##### Uso:\n\n```html\n\u003ccomponent name=\"name_of_component\" componentClass=\"ButtonField\"\u003e\u003c/component\u003e\n```\n\n#### org.quickcorp.components.InputField\n\n**InputField** es una subdefinición de **FormField**, que es comunmete usando para casi el mismo proposito del FormField. La principal diferencia entre InputField y FormField es que InputField tiene un elemento DOM **```\u003cinput\u003e```** como el cuerpo del componente por defecto. Y FormField no tiene un cuerpo predefinido.\n\n##### Uso:\n\n```html\n\u003ccomponent name=\"name_of_component\" componentClass=\"InputField\"\u003e\u003c/component\u003e\n```\n\n\n#### org.quickcorp.components.TextField\n\n**ButtonField** es una subdefinición de **FormField**, que es comunmete usando para casi el mismo proposito del FormField. La principal diferencia entre InputField, ButtonField y FormField es que ButtonField tiene un elemento DOM **```\u003ctextarea\u003e```** como el cuerpo del componente por defecto. Y FormField no tiene un cuerpo predefinido.\n\n##### Uso:\n\n```html\n\u003ccomponent name=\"name_of_component\" componentClass=\"TextField\"\u003e\u003c/component\u003e\n```\n\n\n#### org.quickcorp.components.EmailField\n\n**EmailField** es una subdefinición de **FormField**, que es comunmete usando para casi el mismo proposito del FormField. La principal diferencia entre ButtonField y FormField es que ButtonField tiene un elemento DOM **```\u003cinput\u003e```** como el cuerpo del componente por defecto. Y FormField no tiene un cuerpo predefinido.\n\n##### Uso:\n\n```html\n\u003ccomponent name=\"name_of_component\" componentClass=\"EmailField\"\u003e\u003c/component\u003e\n```\n\n#### org.quickcorp.components.GridComponent\n\nGridComponent tiene un nombre predefinido asignado al valor \"grid\", así que tenlo en cuenta cuando uses esta clase de componente. Tambien  GridComponent está diseñado para usarse junto con GridController para expandir su comportamiento a una cuadrícula CSS.\n\n##### Uso:\n\n```html\n\u003ccomponent componentClass=\"GridComponent\" ...\u003e\u003c/component\u003e\n```\n\n##### Ejemplo:\n\n```html\n\u003ccomponent rows=\"2\" cols=\"2\" componentClass=\"GridComponent\" controllerClass=\"GridController\"\u003e\n  \u003c!-- It is recommended to use subcomponents as the Grid elements--\u003e\n\t\u003ccomponent name=\"name_of_subcomponent1\"\u003e\u003c/component\u003e\n\t\u003ccomponent name=\"name_of_subcomponent2\"\u003e\u003c/component\u003e\n\t\u003ccomponent name=\"name_of_subcomponent3\"\u003e\u003c/component\u003e\n\t\u003ccomponent name=\"name_of_subcomponent4\"\u003e\u003c/component\u003e\n\u003c/controller\u003e\n```\n\nEl ejemplo anterior dibujará una cuadrícula css de dos columnas y dos filas y colocará los subcomponentes en ella.\n\nNo olvides este archivo:\n```html\n\u003c!-- file: grid.tpl.html, you can use the grid template either to draw the grid itself or to draw a loading information --\u003e\n\u003cp\u003eLoading grid...\u003c/p\u003e\n```\n\n#### org.quickcorp.components.ModalEnclosureComponent\n\n#### org.quickcorp.components.ModalComponent\n\n#### org.quickcorp.components.SwaggerUIComponent\n\nSe usa para inyectar un DOM swagger-ui necesario para la Swagger UI API. Obtenga más información en este artículo de QCObjects DevBlog llamado [Working with Swagger UI as a QCObjects Component](https://devblog.qcobjects.org/working-with-swagger-ui-as-a-qcobjects-component-ck6xzoqkg05indfs1i4rxq72e)\n\n##### Uso:\n```html\n\u003ccomponent componentClass=\"SwaggerUIComponent\" controllerClass=\"SwaggerUIController\" \u003e\u003c/component\u003e\n```\n\n#### org.quickcorp.components.splashscreen.VideoSplashScreenComponent\n\nUna potente definición de componente que le permite crear una impresionante pantalla de bienvenida de video para su aplicación web progresiva.\n\n##### Ejemplo:\n```html\n\u003c!-- Add the splash screen component tag as the first component in your HTML document --\u003e\n\u003ccomponent componentClass=\"VideoSplashScreenComponent\"\n\tdata-background=\"./img/splash/splashscreen-aqua.png\"\n\tdata-video_mp4=\"./img/splash/splashscreen-aqua.mp4\"\n\tdata-video_webm=\"./img/splash/splashscreen-aqua.webm\"\n\tdata-video_ogg=\"./img/splash/splashscreen-aqua.ogv\" duration=\"5000\"\u003e\n\t\u003cimg slot=\"logo\" alt=\"logo\" src=\"./img/logo-qcobjects-white.svg\"\u003e\u003c/div\u003e\n\u003c/component\u003e\n\u003c!-- Then you can put your main component as always --\u003e\n\u003ccomponent name=\"main\" cached=true controllerClass=\"MainController\"\u003e\n\u003c/component\u003e\n```\n\n### SDK Controllers\n\n#### org.quickcorp.controllers.GridController\n\n**GridController** está destinado a ser utilizado junto con **GridComponent** para permitir crear una cuadricula CSS para colocar los subcompnentes. Más información [org.quickcorp.components.GridComponent](#org.quickcorp.components.GridComponent)\n\n#### org.quickcorp.controllers.DataGridController\n\n**DataGridController** tomará los datos de su componente y asignará un conjunto de subcomponentes para completarlo.\nEsto se usa comúnmente para renderizar una lista dinámica de componentes. Es usando un valor de atributo **subcomponentClass** en la etiqueta **component** para determinar que definición de componente usar para construir y renderizar cada subcomponente. Los datos en cada subcomponente seran completados con el valor de un elemento mapeado a un subcomponente.\n\n\n##### Uso:\n\n```html\n\u003ccomponent name=\"name_of_component\" controllerClass=\"DataGridController\" subcomponentClass=\"SubComponentClass\"\u003e\n\u003c/component\u003e\n```\n\n##### Ejemplo:\n\nSupón que tienes que representar una lista de perfiles. Cada perfil tiene una foto de perfil, un nombre y un correo electrónico.\nDeseas usar una tarjeta(card) para representar cada perfil de la lista.\n\nAsí que defines un CardComponent para renderizar la foto, el nombre y el email en un elemento en la lista.\n\n```javascript\nClass(\"CardComponent\",Component,{\n\tname:\"card\", // this will point to templates/components/card.tpl.html\n\tdata:{ // the value of this object will be overriden by DataGridController\n\t\tname:\"\u003cname of contact\u003e\",\n\t\temail:\"email@example.com\",\n\t\tprofilePicture:\"img/photo.png\"\n\t}\n})\n```\n\n```html\n\u003c!-- template: card.tpl.html --\u003e\n\u003cimg src=\"{{profilePicture}}\"/\u003e\n\u003ch3\u003e{{name}}\u003c/h3\u003e\n\u003cp\u003e{{email}}\u003c/p\u003e\n```\n\nLuego, debes colocar un componente para generar la lista de tarjetas(cards).\n\n```html\n\u003ccomponent name=\"loading_list\" componentClass=\"MyListComponent\" controllerClass=\"DataGridController\"\nsubcomponentClass=\"CardComponent\"\u003e\n\u003c/component\u003e\n```\n\n```html\n\u003c!-- template: loading_list.tpl.html --\u003e\n\u003cp\u003eLoading list...\u003c/p\u003e\n```\n\nPor último, debes  definir MyListComponent para asignar los datos dinámicos de la lista.\n\n```javascript\nClass(\"MyListComponent\",Component,{\n\tdata:[\n\t\t{ // the value of this object will be mapped to a subcomponent by DataGridController\n\t\t\tname:\"\u003cname of contact\u003e\",\n\t\t\temail:\"email@example.com\",\n\t\t\tprofilePicture:\"img/photo.png\"\n\t\t},\n\t\t{ // the value of this object will be mapped to a subcomponent by DataGridController\n\t\t\tname:\"\u003cname of contact\u003e\",\n\t\t\temail:\"email@example.com\",\n\t\t\tprofilePicture:\"img/photo.png\"\n\t\t},\n\t\t{ // the value of this object will be mapped to a subcomponent by DataGridController\n\t\t\tname:\"\u003cname of contact\u003e\",\n\t\t\temail:\"email@example.com\",\n\t\t\tprofilePicture:\"img/photo.png\"\n\t\t}\n\t]\n})\n```\n\nEl componente resultante sera una lista de **CardComponent** con los datos de cada perfil dentro de ellos mediante **DataGridController**.\n\n#### org.quickcorp.controllers.ModalController\n\n#### org.quickcorp.controllers.FormValidations\n\n**FormValidations** se utiliza para manejar validaciones predeterminadas para **FormController**\n\n#### Uso:\n\n```html\nFormValidations.getDefault(validationName)\n```\n\nDonde **validationName** es el nombre de la validación presente en la propiedad **validations** del **FormController**\n\n#### org.quickcorp.controllers.FormController\n\nLa definición FormController esta destinado a ayudarte a manejar formas dinámicas. Mediante el uso de la sintaxis normalizada de la definición FormController, no tienes que codificar la complejidad de la lógica de un formulario de envío, ya que se atomiza aquí en tres pasos.\n\n- Asigna una serviceClass\n- define los formSettings\n- Asignar código qr las validaciones de campo\n\n##### [FormController].serviceClass\n\nEs el nombre de cadena de la definición de clase. FormController cargará esta clase usando la función auxiliar ClassFactory, por lo que el nombre puede ser un nombre completo del paquete más una definición.\n\n##### [FormController].formSettings\n\nEs un objeto con las propiedades especiales del formulario. La configuración predeterminada es: backRouting:'#', loadingRouting:'#loading', nextRouting:'#signupsuccessful'. Estas configuraciones están destinadas a manejar el comportamiento de flujo del formulario.\n\n**loadingRouting** es el nombre de la ruta que se activará mientras **serviceClass** comience a llamar hasta ue el servicio de recarga regrese la respuesta.\n\n**backRouting** es el nombre del enrutamiento que se activará si falla la llamada a **serviceClass**.\n\n**nextRouting** es el nombre del enrutamiento que se activará cuando la llamada para **serviceClass** finalice bien.\n\n##### [FormController].validations\n\nEs un objeto con las funciones de ayuda que quieres para definir validando cada campo de formulario. Cuando defines una función de validación para un campo, FormController te preguntara si la ejecución de esa función regresa verdadera antes de enviar el formulario.\n\nPara definir validaciones para los campos del formulario, solo necesitas agregarlas como parte de la propiedad de validaciones.\n\n##### Uso:\n\n```javascript\n\t// Let's say you have a form field called \"name\"\n\tvalidations: {\n\t\tname (){\n\t\t\treturn (fieldName, dataValue, element)=\u003e {\n\t\t\t\treturn [true ... or false condition];\n\t\t\t}\n\t\t}, //... add a validation for every form field that you want to be validated\n\t}\n```\n\nTambien puede usar **FormValidations.getDefault** por simplicidad.\n\n```javascript\n\t// Let's say you have a form field called \"name\"\n\tvalidations: {\n\t\tname (){\n\t\t\treturn FormValidations.getDefault('name')\n\t\t}, //... add a validation for every form field that you want to be validated\n\t}\n```\n\n\n\n##### [FormController].formSaveTouchHandler\n\nEste metodo esta internamente usado mediante FormController para llamar al  serviceClass como una acción de envío.\nSe vinculará a cualquier evento de clic o toque de cualquier elemento dentro del formulario que tenga asignada una clase CSS \".submit\".\n\nEjemplo:\n\n```html\n\u003cbutton class=\"submit\"\u003e\u003cp\u003eSend\u003c/p\u003e\u003c/button\u003e\n```\n\nCuando el clic o el toque del anterior botón se active, FormController llamara al servicio definido en **serviceClass**, esta acción se hará por **formSaveTouchHandler**. Si desea cambiar este comportamiento, simplemente anule este método en su controlador personalizado.\n\n##### A complete example of FormController\n\nA continuación se muestra un ejemplo completo de una definición para un Formulario de registro utilizando FormController.\n\n```javascript\n// First, define a service class that will be called on submit.\nClass('SignupClientService',JSONService,{\n\tname:'signup',\n\texternal:true,\n\tcached:false,\n\tmethod:'POST',\n\turl:Service.basePath+'createaccount',\n\twithCredentials:false,\n\t_new_:()=\u003e{\n\t\t// service instantiated\n\t},\n\tdone:(successfulResponse)=\u003e{\n\t\t// service loaded\n\t\t\t_super_('JSONService','done').call(successfulResponse.service,successfulResponse);\n\t\t\tconsole.log(successfulResponse.service.JSONresponse);\n\t}\n})\n```\n\n```javascript\n// To safe extend FormController, we extend first from Controller, then\n// we use a defaultController to instance a new FormController\nClass('SignupFormController',Controller,{\n\tserviceClass: 'SignupClientService',\n\tformSettings:{ /* routings that will be triggered once the serviceClass is called*/\n\t\tbackRouting:'#',\n\t\tloadingRouting:'#loading',\n\t\tnextRouting:'#signupsuccessful'\n\t},\n\tvalidations: { /* validation definitions for every field in the form to be validated before submit */\n\t\tname (){\n\t\t\treturn FormValidations.getDefault('name')\n\t\t},\n\t\temail (){\n\t\t\treturn FormValidations.getDefault('email')\n\t\t},\n\t\tcomment (){\n\t\t\treturn function (fieldName, dataValue, element){\n\t\t\t\treturn (dataValue !== '')?(true):(false);\n\t\t\t}\n\t\t}\n\t},\n\tdefaulController:null,\n\t_new_:function (o){\n\t\to.serviceClass = this.serviceClass;\n\t\to.formSettings = this.formSettings;\n\t\to.validations = this.validations;\n\t\t// here we instance a defaultController with a New FormController\n\t\t// passing the o object declaration coming from the components stack building process.\n\t\tthis.defaulController = New(FormController,o);\n\t},\n\tdone: function (){\n\t\t// we define a custom done callback function to inject a custom behavior as well as calling the defaultController behavior\n\t\tlogger.debugEnabled=true;\n\t\tvar controller = this.defaulController;\n\t\ttry {\n\t\t\tcontroller.done.call(controller);\n\t\t}catch (e){\n\t\t\tlogger.debug('Unable to execute default behavior');\n\t\t}\n\t}\n})\n```\n\n```html\n\u003c!-- A Shadowed Component to render the signup forms --\u003e\n\u003c!-- template: signup-form.tpl.html --\u003e\n\n\u003cform action=\"#\" style=\"border:1px solid #ccc;border-radius:20px\"\u003e\n\t\u003cdiv class=\"container\"\u003e\n\t\t\u003cslot name=\"title\"\u003e\n\t\t\t\u003ch1\u003eSignup Form\u003c/h1\u003e\n\t\t\u003c/slot\u003e\n\t\t\u003cslot name=\"subtitle\"\u003e\n\t\t\t\u003cp\u003ePlease fill up this form to ask for a quote.\u003c/p\u003e\n\t\t\u003c/slot\u003e\n\t\t\u003chr /\u003e\n\t\t\u003cslot id=\"field_control\" name=\"field-control\"\u003e\n\t\t\u003c/slot\u003e\n\t\t\u003chr /\u003e\n\t\t\u003cslot name=\"submit_button\"\u003e\u003c/slot\u003e\n\t\u003c/div\u003e\n\u003c/form\u003e\n```\n\n```html\n\u003c!-- A signup form using the shadowed component signup-form --\u003e\n\u003c!-- template: signup.tpl.html --\u003e\n\u003ccomponent name=\"signup-form\" shadowed=\"true\" controllerClass=\"SignupFormController\"\u003e\n  \u003ch1 slot=\"title\"\u003eSignup Form\u003c/h1\u003e\n  \u003cp slot=\"subtitle\"\u003ePlease fill up this form to ask for a quote.\u003c/p\u003e\n  \u003clabel slot=\"field-control\" id=\"name_label\" for=\"name\"\u003e\u003cb\u003e\u0026#x1F9D1; Full Name\u003c/b\u003e\u003c/label\u003e\n  \u003cinput slot=\"field-control\" type=\"text\" pattern=\"^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$\" title=\"Please write your full name\" placeholder=\"Full Name\" name=\"name\" data-field=\"name\" aria-labelledby=\"name_label\" required\u003e\n  \u003clabel slot=\"field-control\" id=\"email_label\" for=\"email\"\u003e\u003cb\u003e\u0026#x1F4E7; Email\u003c/b\u003e\u003c/label\u003e\n  \u003cinput slot=\"field-control\" type=\"email\" pattern=\"^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$\" title=\"Please write a right email address\" placeholder=\"Enter Email\" name=\"email\" data-field=\"email\" aria-labelledby=\"email_label\" required\u003e\n  \u003clabel slot=\"field-control\" for=\"comment\" id=\"comment_label\"\u003e\u003cb\u003e\u0026#x1F4DD; Comment\u003c/b\u003e\u003c/label\u003e\n  \u003ctextarea slot=\"field-control\" name=\"comment\" title=\"Please write a comment\" rows=\"10\" cols=\"100\" data-field=\"comment\" aria-labelledby=\"comment_label\"\u003e\u003c/textarea\u003e\n  \u003cp slot=\"field-control\"\u003eBy submitting this form you agree to our \u003ca href=\"#\" style=\"color:dodgerblue\"\u003eTerms \u0026 Privacy\u003c/a\u003e.\u003c/p\u003e\n\t\u003cdiv class=\"clearfix\"\u003e\n\t    \u003cbutton aria-label=\"Cancel\" onclick=\"location.href='/#'\" role=\"button\" tabindex=\"-1\" type=\"button\" class=\"cancelbtn\"\u003e\u003cp\u003eCancel\u003c/p\u003e\u003c/button\u003e\n\t    \u003cbutton  aria-label=\"Send\" role=\"button\" tabindex=\"-1\" type=\"button\" class=\"signupbtn submit\"\u003e\u003cp\u003eSend\u003c/p\u003e\u003c/button\u003e\n\t\u003c/div\u003e\n\u003c/component\u003e\n```\n\n#### org.quickcorp.controllers.SwaggerUIController\n\nEs usado para inyectar un swagger-ui DOM necesario para el Swagger UI API. Aprende mas en este articulo de QCObjects DevBlog llamado [Working with Swagger UI as a QCObjects Component](https://devblog.qcobjects.org/working-with-swagger-ui-as-a-qcobjects-component-ck6xzoqkg05indfs1i4rxq72e)\n\n##### Uso:\n```html\n\u003ccomponent componentClass=\"SwaggerUIComponent\" controllerClass=\"SwaggerUIController\" \u003e\u003c/component\u003e\n```\n\n\n### SDK Effects\n\nQCObjects tiene una definicion  **Effect**  para manejar y producir nuevos efectos y transiciones para los componentes. A continuación hay algunas definiciones de efectos personalizadas que te ayudaran a construir sorprendentes características visuales para tus componentes. Para mejorar el rendimiento, los efectos están cambiando CSS internamente para aplicar el efecto de manera inteligente. Y todo el motor de efectos se basa en la definición **requestAnimationFrame**, lee mas sobre esto [aquí](https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#animation-frames)\n\n#### org.quickcorp.tools.effects.Move\n\nMueve el objeto DOM de una posicion a otra.\n\n##### Uso:\n\n```javascript\nMove.apply(element, xfrom, yfrom, xto, yto)\n```\n\n##### Ejemplo:\n\n```javascript\n// The next line will move all the images from (0,0) to (10,10)\nTag('img').map(img =\u003e Move.apply(img,0,0,10,10))\n```\n\n#### org.quickcorp.tools.effects.MoveXInFromRight\n\nMueve un elemento desde el lado derecho en el eje X a la posición original del objeto.\n\n##### Uso:\n\n```javascript\nMoveXInFromRight.apply(element)\n```\n\n##### Ejemplo:\n\n```javascript\n// the next line will move every canvas on the document from right side to its original position\nTag('canvas').map(canvas =\u003e MoveXInFromRight.apply(canvas));\n```\n\n#### org.quickcorp.tools.effects.MoveXInFromLeft\n\nMueve un elemento desde el lado izquierdo en el eje X a la posición original del objeto.\n\n##### Uso:\n\n```javascript\nMoveXInFromLeft.apply(element)\n```\n\n##### Ejemplo:\n\n```javascript\n// the next line will move every canvas on the document from left side to its original position\nTag('canvas').map(canvas =\u003e MoveXInFromLeft.apply(canvas));\n```\n\n#### org.quickcorp.tools.effects.MoveYInFromBottom\n\nMueve un objeto del DOM desde abajo a su posición original usando el eje Y.\n\n##### Uso:\n```javascript\nMoveYInFromBottom.apply(element)\n```\n\n##### Ejemplo:\n```javascript\n// the next line will move the body of every component named \"comp1\" from bottom to its original position\nTag('component[name=comp1]').map(componentBody =\u003e MoveYInFromBottom.apply(componentBody));\n```\n\n#### org.quickcorp.tools.effects.MoveYInFromTop\n\nMueve un objeto del DOM de arriba a su posición original usando el eje Y.\n\n##### Uso:\n```javascript\nMoveYInFromTop.apply(element)\n```\n\n##### Ejemplo:\n```javascript\n// the next line will move the body of every component named \"comp1\" from top to its original position\nTag('component[name=comp1]').map(componentBody =\u003e MoveYInFromTop.apply(componentBody));\n```\n\n#### org.quickcorp.tools.effects.RotateX\n\nRota un objeto en el eje X.\n\n##### Uso:\n```javascript\nRotateX.apply(element, angleFrom, angleTo)\n```\n\n**angleFrom** y **angleTo** representan un valor de ángulo expresado en grados, comenzando desde 0 (cero) a 360.\n\n##### Ejemplo:\n```javascript\n// the next line will rotate in X axis the div called #id from 180 degrees to 240 degrees\nTag('div#id').map(div =\u003e RotateX.apply(div, 180, 240));\n```\n\n\n#### org.quickcorp.tools.effects.RotateY\n\nRota un objeto en el eje Y.\n\n##### Uso:\n```javascript\nRotateY.apply(element, angleFrom, angleTo)\n```\n\n**angleFrom** y **angleTo** representan un valor de ángulo expresado en grados, comenzando desde 0 (cero) a 360.\n\n##### Ejemplo:\n```javascript\n// the next line will rotate in Y axis the div called #id from 0 degrees to 270 degrees\nTag('div#id').map(div =\u003e RotateY.apply(div, 0, 270));\n```\n\n#### org.quickcorp.tools.effects.RotateZ\n\nRota un objeto en el eje Z.\n\n##### Uso:\n```javascript\nRotateZ.apply(element, angleFrom, angleTo)\n```\n\n**angleFrom** y **angleTo** representan un valor de ángulo expresado en grados, comenzando desde 0 (cero) a 360.\n\n##### Ejemplo:\n```javascript\n// the next line will rotate in Z axis the div called #id from 0 degrees to 60 degrees\nTag('div#id').map(div =\u003e RotateZ.apply(div, 0, 60));\n```\n\n\n\n#### org.quickcorp.tools.effects.Rotate\n\nRota un objeto en los ejes X, Y, Z. Todos los ejes rotarán en paralelo al mismo tiempo produciendo una percepción de efectos visuales en 3D.\n\n##### Uso:\n```javascript\nRotate.apply(element, angleFrom, angleTo)\n```\n\n**angleFrom** y **angleTo** representan un valor de ángulo expresado en grados, comenzando desde 0 (cero) a 360.\n\n##### Ejemplo:\n```javascript\n// the next line will rotate in X, Y and Z axes the div called #id form 0 to 270 degrees\nTag('div#id').map(div =\u003e Rotate.apply(div, 0, 270));\n```\n\n#### org.quickcorp.tools.effects.Fade\n\nProduce un efecto de desvanecimiento al reducir la opacidad del elemento.\n\n##### Uso:\n\n```javascript\nFade.apply(element, alphaFrom, alphaTo)\n```\n\n**alphaFrom** y **alphaTo** son numeros entre 0 (cero) y 1.\n\n```javascript\n// the following line will fade a \u003cb class=\"header\"\u003e element from 0.5 (mid visibility) to 1 (full visibility)\nTag('b.header').map(header=\u003eFade.apply(header, 0.5, 1))\n```\n\n#### org.quickcorp.tools.effects.Radius\n\nRedondea la esquina de un elemento.\n\n##### Uso:\n```javascript\nRadius.apply(element, radiusFrom, radiusTo)\n```\n\n**radiusFrom** y **radiusTo** son valores numéricos.\n\n##### Ejemplo:\n```javascript\n// the next line will round the corners of every image in the document\nTag('img').map(element =\u003e Radius.apply(element, 0, 100))\n```\n\n#### org.quickcorp.tools.effects.Resize\n\n##### Uso:\n```javascript\nResize.apply(element, scaleFrom, scaleTo)\n```\n\n**scaleFrom** y **scaleTo** son valores numericos\nUn valor de 1 es tamaño normal, un valor de 2 es tamaño doble, un valor entre 0 y 1 es una escala pequeña.\n\n##### Ejemplo:\n\n```javascript\n// the next line will make a zoom-out effect on every image in the document\nTag('img').map(element =\u003e Resize.apply(element, 2,0))\n\n// the next line will make a zoom-in effect on every image in the document\nTag('img').map(element =\u003e Resize.apply(element, 0,1))\n\n// the next line will make a zoom-in-out effect on every image in the document\nTag('img').map(element =\u003e Resize.apply(element, 2,1))\n```\n\n#### org.quickcorp.tools.effects.WipeLeft\n\nHace un efecto de limpieza desde el lado izquierdo al origen del elemento.\n\n##### Uso:\n```javascript\nWipeLeft.apply(element, scaleFrom, scaleTo)\n```\n\n**scaleFrom** y **scaleTo** son valores numericos.\nUn valor de 1 es tamaño normal, un valor de 2 es tamaño doble, un valor entre 0 y 1 es una escala pequeña.\n\n##### Ejemplo\n\n```javascript\nTag('img').map(element =\u003e Wipe","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FQuickCorp%2FQCObjects","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FQuickCorp%2FQCObjects","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FQuickCorp%2FQCObjects/lists"}