Project

General

Profile

1
/*
2
License: LGPL as per: http://www.gnu.org/copyleft/lesser.html
3
$Id$
4
*/
5

    
6
/**
7
 * Base Class for widgets.  Associates a node on the page with a stylesheet and
8
 * model.  All widgets must extend this base class.
9
 * Defines the default paint() method for all widgets which is where the 
10
 * stylesheet is applied to the model XML document.
11
 * To override widget.paint(), define it before calling this constructor.
12
 * The stylesheet URL defaults to "widget/<widgetName>.xsl" if it is not defined
13
 * in config file.  Set a stylesheet property containing an XSL URL in config
14
 * to customize the stylesheet used.
15
 * All stylesheets will have "modelId" and "widgetId" parameters set when called.
16
 *
17
 * @constructor
18
 * @author Mike Adair 
19
 * @param widget      Pointer to the widget instance being created
20
 * @param widgetNode  The widget's XML object node from the configuration document.
21
 * @param model       The model object that this widget belongs to.
22
 */
23
function WidgetBase(widget,widgetNode,model) {
24
  widget.model = model;
25
  widget.widgetNode = widgetNode;
26

    
27
  /** Method used for painting.
28
   * xsl2html (default) => output of XSL will be HTML.
29
   * xsl2js => output of XSL will be javascript to execute.
30
   * image2html => where the model doc has content type image/*
31
   */
32
  widget.paintMethod="xsl2html";
33

    
34
  /** Widget's Id defined in the Config (required) */
35
  if (widgetNode.attributes.getNamedItem("id")) {
36
    widget.id = widgetNode.attributes.getNamedItem("id").nodeValue;
37
  } else {
38
    alert("id required for object:" + widgetNode.nodeName );
39
  }
40

    
41
  //allow the widget output to be replaced on each paint call
42
  var outputNode = widgetNode.selectSingleNode("mb:outputNodeId");
43
  if ( outputNode ) {
44
    widget.outputNodeId = outputNode.firstChild.nodeValue;
45
  } else {
46
    widget.outputNodeId = "MbWidget_" + mbIds.getId();
47
  }
48

    
49
  //until htmlTagNode becomes required allow setting of it by widget id
50
  if (!widget.htmlTagId) {
51
    var htmlTagNode = widgetNode.selectSingleNode("mb:htmlTagId");
52
    if (htmlTagNode) {
53
      widget.htmlTagId = htmlTagNode.firstChild.nodeValue;
54
    } else {
55
      widget.htmlTagId = widget.id;
56
    }
57
  }
58

    
59
  // Node in main HTML to attach widget to.
60
  widget.node = document.getElementById(widget.htmlTagId);
61
  if(!widget.node) {
62
    //alert("htmlTagId: "+widget.htmlTagId+" for widget "+widgetNode.nodeName+" not found in config");
63
  }
64

    
65
  //set an empty debug property in config to see inputs and outputs of stylehseet
66
  if ( widgetNode.selectSingleNode("mb:debug") ) widget.debug=true;
67

    
68
  /** Transient var used to store model XML before and then after XSL transform.
69
   *  It can be modified by prePaint() .
70
   */
71
  widget.resultDoc = null;
72

    
73
  // Set this.stylesheet
74
  // Defaults to "widget/<widgetName>.xsl" if not defined in config file.
75
  if ( !widget.stylesheet ) {
76
    var styleNode = widgetNode.selectSingleNode("mb:stylesheet");
77
    if (styleNode ) {
78
      widget.stylesheet = new XslProcessor(styleNode.firstChild.nodeValue,model.namespace);
79
    } else {
80
      widget.stylesheet = new XslProcessor(baseDir+"/widget/"+widgetNode.nodeName+".xsl",model.namespace);
81
    }
82
  }
83

    
84
  /**
85
   * Initialize dynamic properties.set the target model
86
   * @param toolRef Pointer to this object.
87
   */
88
  this.initTargetModel = function(objRef) {
89
    //set the target model
90
    var targetModel = objRef.widgetNode.selectSingleNode("mb:targetModel");
91
    if (targetModel) {
92
      objRef.targetModel = eval("config.objects."+targetModel.firstChild.nodeValue);
93
      if ( !objRef.targetModel ) {
94
        alert("error finding targetModel:" + targetModel.firstChild.nodeValue + " for:" + objRef.id);
95
      }
96
    } else {
97
      objRef.targetModel = objRef.model;
98
    }
99
    objRef.stylesheet.setParameter("targetModelId", objRef.targetModel.id );
100
  }
101

    
102

    
103
  // Set stylesheet parameters for all the child nodes from the config file
104
  for (var j=0;j<widgetNode.childNodes.length;j++) {
105
    if (widgetNode.childNodes[j].firstChild
106
      && widgetNode.childNodes[j].firstChild.nodeValue)
107
    {
108
      widget.stylesheet.setParameter(
109
        widgetNode.childNodes[j].nodeName,
110
        widgetNode.childNodes[j].firstChild.nodeValue);
111
    }
112
  }
113

    
114
  // Set widget text values as parameters 
115
  if (config.widgetText) {
116
    var textNodeXpath = "/mb:WidgetText/mb:widgets/mb:" + widgetNode.nodeName;
117
    var textParams = config.widgetText.selectNodes(textNodeXpath+"/*");
118
    for (var j=0;j<textParams.length;j++) {
119
      widget.stylesheet.setParameter(textParams[j].nodeName,textParams[j].firstChild.nodeValue);
120
    }
121
  }
122

    
123
  //all stylesheets will have these properties available
124
  widget.stylesheet.setParameter("modelId", widget.model.id );
125
  widget.stylesheet.setParameter("modelTitle", widget.model.title );
126
  widget.stylesheet.setParameter("widgetId", widget.id );
127
  widget.stylesheet.setParameter("skinDir", config.skinDir );
128
  widget.stylesheet.setParameter("lang", config.lang );
129

    
130
  /**
131
   * Move this widget to the absolute (left,top) position in the browser.
132
   * @param left Absolute left coordinate.
133
   * @param top Absolute top coordinate.
134
   */
135
  this.move = function(left,top) {
136
    this.node.style.left = left;
137
    this.node.style.top = top;
138
  }
139

    
140
  /**
141
   * Resize this widget.
142
   * @param width New width.
143
   * @param height New height.
144
   */
145
  this.resize = function(width,height) {
146
    this.node.style.width = width;
147
    this.node.style.height = height;
148
  }
149

    
150
  /**
151
   * Called change the visibility of this widget's output node
152
   * @param vis   boolean true or false 
153
   */
154
  this.setVisibility = function(vis) {
155
    var vis="visible";
156
    if (vis) vis="hidden";
157
    document.getElementById(this.outputNodeId).style.visibility = vis;
158
  }
159

    
160
  /**
161
   * Called before paint(), can be used to set up a widget's paint parameters,
162
   * or modify model using this.resultDoc().
163
   * @param objRef Pointer to this object.
164
   */
165
  this.prePaint = function(objRef) {
166
    //no-op by default
167
  }
168

    
169
  /**
170
   * Called after paint(), can be used to initialize things that depend on the
171
   * the widget output being presetn, eg. form and form elements
172
   * @param objRef Pointer to this object.
173
   */
174
  this.postPaint = function(objRef) {
175
    //no-op by default
176
  }
177

    
178

    
179

    
180

    
181

    
182

    
183
//to override the paint method, define it in the exetnsion class before calling 
184
//the WidgetBase constructor.  This is so that when paint is registered as a
185
//listener, the method from the instance is used.
186
if (!widget.paint) {
187

    
188
  /**
189
   * Render the widget.
190
   * @param objRef Pointer to widget object.
191
   */
192

    
193
	
194
 this.paint = function(objRef) {
195

    
196
    if (objRef.model.template) return;
197

    
198
    // Remove widget from display if the model is empty
199
    if (!objRef.model.doc){
200
      objRef.clearWidget(objRef);
201
    }
202

    
203
    if (objRef.model.doc && objRef.node) {
204
      objRef.stylesheet.setParameter("modelUrl", objRef.model.url);
205

    
206
      //if (objRef.debug) alert("source:"+Sarissa.serialize(objRef.model.doc));
207
      objRef.resultDoc = objRef.model.doc; // resultDoc sometimes modified by prePaint()
208
      objRef.prePaint(objRef);
209

    
210
      //confirm inputs
211
      if (objRef.debug) alert("prepaint:"+Sarissa.serialize(objRef.resultDoc));
212
      if (objRef.debug) alert("stylesheet:"+Sarissa.serialize(objRef.stylesheet.xslDom));
213

    
214
      //set to output to a temporary node
215
      //hack to get by doc parsing problem in IE
216
      //the firstChild of tempNode will be the root element output by the stylesheet
217
      var outputNode = document.getElementById( objRef.outputNodeId );
218
      var tempNode = document.createElement("DIV");
219
      switch (objRef.paintMethod) {
220
        case "xsl2html":
221
          //process the doc with the stylesheet
222
          var s = objRef.stylesheet.transformNodeToString(objRef.resultDoc);
223
          if (config.serializeUrl && objRef.debug) postLoad(config.serializeUrl, s);
224
          if (objRef.debug) alert("painting:"+objRef.id+":"+s);
225
          tempNode.innerHTML = s;
226
          tempNode.firstChild.setAttribute("id", objRef.outputNodeId);
227

    
228
          //look for this widgets output and replace if found,
229
          //otherwise append it
230
          if (outputNode) {
231
            objRef.node.replaceChild(tempNode.firstChild,outputNode);
232
          } else {
233
            objRef.node.appendChild(tempNode.firstChild);
234
          }
235
          break;
236
        case "image2html":
237
          //here the model document is an image
238
          tempNode.style.position="absolute";
239
          tempNode.style.top=0;
240
          tempNode.style.left=0;
241
          tempNode.appendChild(objRef.model.doc);
242
          tempNode.setAttribute("id", objRef.outputNodeId);
243

    
244
          //look for this widgets output and replace if found,
245
          //otherwise append it
246
          if (outputNode) {
247
            objRef.node.replaceChild(tempNode,outputNode);
248
          } else {
249
            objRef.node.appendChild(tempNode);
250
          }
251
          break;
252
        case "xsl2js":
253
          jsNode = objRef.stylesheet.transformNodeToObject(objRef.resultDoc);
254
          js=jsNode.selectSingleNode("js").firstChild.nodeValue;
255
          tempNode.style.position="absolute";
256
          tempNode.style.top=0;
257
          tempNode.style.left=0;
258
          tempNode.setAttribute("id", objRef.outputNodeId);
259
          //look for this widgets output and replace if found,
260
          //otherwise append it
261
          if (outputNode) {
262
            objRef.node.replaceChild(tempNode,outputNode);
263
          } else {
264
            objRef.node.appendChild(tempNode);
265
          }
266
          if (objRef.debug) alert("javascript eval:"+js);
267
          objRef.model.setParam("modelStatus","rendering");
268
          eval(js);
269

    
270
          break;
271
		//Michael Jenik added this case for the MapContainer Paint
272
		case "preloading":
273
        break;
274

    
275
        default:
276
          alert("WidgetBase: Invalid paintMethod="+objRef.paintMethod);
277
      }
278

    
279
      objRef.postPaint(objRef);
280
    }
281
  }
282
}
283

    
284
  /**
285
   * Remove widget from display.
286
   * @param objRef Pointer to this object.
287
   */ 
288
  this.clearWidget = function(objRef) {
289
    //with objRef.node remove child
290
    var outputNode = document.getElementById( objRef.outputNodeId );
291
    if (outputNode) objRef.node.removeChild(outputNode);
292
  }
293

    
294
  // If this object is being created because a child is extending this object,
295
  // then child.properties = this.properties
296
  for (sProperty in this) {
297
    widget[sProperty] = this[sProperty];
298
  }
299

    
300
  // Call paint when model changes
301
  widget.model.addListener("init", widget.initTargetModel, widget);
302
  widget.model.addListener("refresh",widget.paint, widget);
303
  widget.model.addListener("newModel",widget.clearWidget, widget);
304
}
(135-135/145)