1 /**
  2 * @fileOverview File contains AMI.ModuleComponent base class required to create own module components.
  3 */
  4  
  5 /**
  6 * Base component class contains all required functionality for component work. This couldn't be used directly and should be inherited in custom component class.
  7 * @example <strong>Example of inheriting this class:</strong>
  8 * AMI.ModuleComponentCustom = function(oModule, componentType, componentId){
  9 *     AMI.ModuleComponentCustom.superclass.constructor.call(this, oModule, componentType, componentId);
 10 *     // Custom objects definitioun here
 11 *     this.init();
 12 * }
 13 * AMI.inherit(AMI.ModuleComponentCustom, AMI.ModuleComponent);
 14 * 
 15 * @class Base module component class that releases default functionality.
 16 * @param {AMI.Module} oModule Module object.
 17 * @param {string} componentType Type of component (filter_form, form, list).
 18 * @param {string} componentId Id of current component.
 19 */
 20 AMI.ModuleComponent = function(oModule, componentType, componentId){
 21     this.componentType = componentType;
 22     this.modAction = '';
 23     this.modActionId = null;
 24     this.hashDataFilter = '.*';
 25     this.oModule = oModule;
 26     this.componentId = componentId;
 27     this.oContainer = null;
 28     this.oLoaderOverlay = null;
 29     this.oLoader = null;
 30     this.getContentData = {};
 31 
 32     this.oDebug = null;
 33 
 34     /**
 35     * Create component place and request its content
 36     * 
 37     * @constructs
 38     * @returns {void}
 39     */
 40     this.init = function(){
 41         this.setObject();
 42     }
 43 
 44     /**
 45     * Get module id of current component.
 46     * 
 47     * @returns {string} Module id.
 48     */    
 49     this.getModuleId = function(){
 50         return this.oModule.moduleId;
 51     }
 52 
 53     /**
 54     * Create component place and loader on the page with id component_{module id}_{component type}_{component id}. Also request content of component.
 55     * 
 56     * @returns {void}
 57     */
 58     this.setObject = function(){
 59         var componentIdDoc = 'component_' + this.oModule.moduleId + '_' + this.componentType + '_' + this.componentId;
 60 
 61         this.oContainer = AMI.find('#' + componentIdDoc);
 62         if(this.oContainer == null){
 63             this.oContainer = AMI.Browser.DOM.create(
 64                 'DIV',
 65                 componentIdDoc,
 66                 'modPageComponent',
 67                 '',
 68                 this.oModule.getContainer()
 69             );
 70         }
 71 
 72         this.oLoaderOverlay = AMI.find('#' + componentIdDoc + 'Overlay');
 73         if(this.oLoaderOverlay == null){
 74             this.oLoaderOverlay = AMI.Browser.DOM.create(
 75                 'DIV',
 76                 componentIdDoc + 'Overlay',
 77                 'componentLoaderOverlay',
 78                 '',
 79                 this.oModule.getContainer()
 80             );
 81         }
 82 
 83         this.oLoader = AMI.find('#' + componentIdDoc + 'Loader');
 84         if(this.oLoader == null){
 85             this.oLoader = AMI.Browser.DOM.create(
 86                 'DIV',
 87                 componentIdDoc + 'Loader',
 88                 'componentLoader',
 89                 '',
 90                 this.oModule.getContainer()
 91             );
 92         }
 93 
 94         AMI.Browser.Event.addHandler(this.oContainer, 'click', function(_this){return function(evt){return _this.oModule.onComponentClick(evt, _this)}}(this));
 95     }
 96 
 97     /**
 98     * Show component loader with background overlay.
 99     * 
100     * @returns {void}
101     */
102     this.showLoader = function(){
103         var oLoaderOverlay = this.oLoaderOverlay.cloneNode(true);
104         oLoaderOverlay = this.oContainer.appendChild(oLoaderOverlay);
105         oLoaderOverlay.id = '';
106         oLoaderOverlay.style.display = 'block';
107 
108         var oLoader = this.oLoader.cloneNode(true);
109         oLoader = this.oContainer.appendChild(oLoader);
110         oLoader.id = '';
111         oLoader.style.display = 'block';
112     }
113 
114     /**
115     * Hide loader with background overlay.
116     * 
117     * @returns {void}
118     */
119     this.hideLoader = function(){
120         var aLoaderOverlays = AMI.find('.componentLoaderOverlay');
121         for(var i = aLoaderOverlays.length - 1; i >= 0; i--){
122             aLoaderOverlays[i].parentNode.removeChild(aLoaderOverlays[i]);
123         }
124 
125         var aLoader = AMI.find('.componentLoader');
126         for(var i = aLoader.length - 1; i >= 0; i--){
127             aLoader[i].parentNode.removeChild(aLoader[i]);
128         }
129     }
130 
131     /**
132     * Request component content from server. When responce is received this.onContentReceived is called.
133     * 
134     * @returns {void}
135     */
136     this.getContent = function(){
137         this.showLoader();
138 
139         oParameters = {
140             'mod_id': this.oModule.moduleId,
141             'mod_action': this.modAction
142         };
143 
144         if(this.modActionId != null){
145         	oParameters.mod_action_id = this.modActionId;
146         }
147 
148         AMI.Message.send('ON_COMPONENT_GET_REQUEST_DATA', this, oParameters);
149 
150         AMI.HTTPRequest.getContent(
151             'GET',
152             amiModuleLink || '',
153             oParameters,
154             function(_this){return function(state, content){_this.onContentReceived(state, content)}}(this)
155         );
156     }
157 
158     /**
159     * Callback for this.getContent. AMI.HTTPRequest calls this method when content is received.
160     * Before placing content to component area method sends ON_COMPONENT_CONTENT_RECEIVED message.
161     * After the content is placed ON_COMPONENT_CONTENT_PLACED will be sent.
162     * 
163     * @param {number} state XHR responce state. 1 = success.
164     * @param {string} content Response from server.
165     * @returns {void}
166     */
167     this.onContentReceived = function(state, content){
168         this.hideLoader();
169 
170         if(state == 1){
171             if(content.substr(0, 1) == '{' && content.substr(content.length - 1, 1) == '}'){
172                 var oData = AMI.String.decodeJSON(content);
173                 if(typeof(oData) != 'object' || typeof(oData.data) == 'undefined'){
174                     oData = {'content': content};
175                 }
176             }else{
177                 oData = {'content': content};
178             }
179             AMI.Message.send('ON_COMPONENT_CONTENT_RECEIVED', this, oData);
180 
181             if(typeof(oData.content) != 'undefined'){
182                 this.oDebug = null;
183                 AMI.Browser.DOM.setInnerHTML(this.oContainer, oData.content);
184             }else{
185                 this.setBlockDataFromObject(oData);
186 
187                 if(typeof(oData.debug) != 'undefined'){
188                     this.setDebug(oData.debug);
189                 }
190 
191                 if(typeof(oData.message) != 'undefined'){
192                     alert(AMI.Template.Locale.get(oData.message));
193                 }
194             }
195             this.onComponentContentPlaced();
196             AMI.Message.send('ON_COMPONENT_CONTENT_PLACED', this);
197         }
198     }
199 
200     /**
201     * Method that could be overriden. Called after the component placed its content.
202     * 
203     * @returns {void}
204     */
205     this.onComponentContentPlaced = function(){
206     };
207 
208     /**
209     * Method that should be overriden. Called when content for component received and the content is object.
210     * 
211     * @param {object} oData Evalled content that was received from server.
212     * @returns {void}
213     */
214     this.setBlockDataFromObject = function(oData){
215         AMI.Browser.DOM.setInnerHTML(this.oContainer, 'Data parsing function is not exists for component ' + this.componentId);
216     }
217 
218     /**
219     * Set debug container if absent for component area and print debug content.
220     * 
221     * @param {string} debugData Debug string that will be printed separatelly in debug block.
222     * @returns {void}
223     */
224     this.setDebug = function(debugData){
225         if(typeof(DEBUG_BY_IP) != 'undefined' && DEBUG_BY_IP){
226             if(this.oDebug == null){
227                 this.oDebug = AMI.Browser.DOM.create('div', '', 'componentDebug', '', null);
228                 this.oDebug = this.oContainer.insertBefore(this.oDebug, this.oContainer.firstChild);
229             }
230             this.oDebug.innerHTML = '<div style="background: red; height: 1px; margin-bottom: 5px; overflow: hidden;"></div>' + debugData + this.oDebug.innerHTML;
231         }
232     }
233 
234     /**
235     * Get component container that contents component data.
236     * 
237     * @returns {DOM object} Object that contains component data.
238     */
239     this.getContainer = function(){
240         return this.oContainer;
241     }
242 
243     /**
244     * Get the filter for hash data. Filter required to select parameters for current component only. For example, flt_ for filter etc. By default it is ".*".
245     * 
246     * @returns {string} Hash filter string.
247     */
248     this.getHashDataFilter = function(){
249         return this.hashDataFilter;
250     }
251 }
252