jQuery - nach Instanz Options ändern

crsakawolf

Erfahrenes Mitglied
Hallo Freunde,

ich habe jetzt haufen weise Literatur zu Rate gezogen, aber bin leider nicht fündig geworden.

Folgendes Problem:
Ich Instanziere ein Canvas und lasse darauf ein Diagramm zeichnen.
Nun möchte ich allerdings, z.B. per Knopfdruck auf einen beliebigen Button options meines Diagrammes ändern.
z.B. Hintergrundfarbe, Schriftgröße etc.

Der HTML Code:
HTML:
		<script type="text/javascript">
		var daten = new Array(100,33);
		var legende = new Array('Januar','Februar');
		var daten2 = new Array(1,1);
			$(document).ready(function(){				
				$("#diagramm").diagramm(
						{
							data:daten,
							legend:legende,
							'canvas':
								{'backgroundColor':"#CCC"},
							'diagramm':
								{'ScaleY':5,
								 'color':'#000'
								}
						});
				$('a[name="blue"]').click(function(){
					$( "#diagramm").diagramm({'canvas':{'backgroundColor':"#CCC"}});
				});
			});
		</script>

<body>
	<canvas id="diagramm" class="test">
	
	</canvas>
	<table>
		<tr>
		<td><button name="grey">Grau</button></td>
		<td><button name="red">Rot</button></td>
		<td><a name="blue" onclick="return false;">Blau</button></td>
	</table>
</body>
</html>

Das Widget
Code:
(function($){
	$.widget("ui.diagramm",{
		// Options Standard value
		options: {
			titel: {					// Aussehen des Titels
				marginTop: 		20,
				fontSize: 		10,
				fontFace: 		"Arial",
				text:			"Überschrift",
				postion:		"center"
			},
			diagramm: {					// Diagrammparameter
				marginLeft:		30,
				marginBottom:	30,
				fontSize:		10,
				fontFace:		"Arial",
				ScaleY:			20,		// Y-Skala
				color:			"#FFF"	// Punktfarbe
			},
			canvas: {					// Canvas Parameter
				width:			700,
				height:			300,
				border:			1,
				borderColor:	"#000",
				backgroundColor:"#000"
			},
			data: [1,2,3,4],					// Datenwerte - Array
			legend: ['1','1','1','1']					// Datenlegende - Array
		},
		
		_setOption: function(option, value){	// übergibt Parameter an Options
			 $.Widget.prototype._setOption.apply( this, arguments );  
        },
		
		_create: function(){	// Konstruktor
			
			var self = this;
			opt = this.options;
			ele = this.element;
			
			ele.addClass("test");	
			
			var axisY = new Array(opt.diagramm.marginLeft, opt.canvas.height - opt.diagramm.marginBottom, opt.canvas.height - opt.diagramm.marginBottom * 2); // Position X & Y , Länge 
			var axisX = new Array(opt.diagramm.marginLeft, opt.canvas.height - opt.diagramm.marginBottom, opt.canvas.width - opt.diagramm.marginLeft); // Position X & Y , Länge
			
			axisX_scaling = (Math.ceil((opt.canvas.width - opt.diagramm.marginLeft * 2) / opt.data.length));	// Berechnung der Abstände
			ScaleX_center = axisX_scaling/2;									// Länge der Skalierung durch 2 (Pro abschnitt)
			var ScaleX_center; // Mittelpunkt Skalierung der X - Achse; 

			var myCan = document.getElementById(ele.attr('id')); 
			var Can = myCan.getContext("2d");
			
			this.setCanvas();	// Canvas erstellen
			this.setDiagramm(axisY, axisX,Can);	// Diagramm zeichnen			
			this.setTitel(Can);	// Titel setzen
			
			this.setYscale(opt.data, opt.diagramm.ScaleY, opt.canvas.height - opt.diagramm.marginBottom * 2, axisY, Can);
			this.setXscale(opt.legend, opt.canvas.width - opt.diagramm.marginLeft * 2, axisX, Can);
			this.setDataPoints(opt.data, opt.legend, axisX, axisY, ScaleX_center, opt.canvas.width - opt.diagramm.marginLeft * 2, opt.canvas.height - opt.diagramm.marginBottom * 2, Can);
			
		},
		
		destroy: function(){	// Destructor
			
		},
		
		data: function(daten){
			alert(opt.canvas.backgroundColor);
			opt.data = daten;
			var axisY = new Array(opt.diagramm.marginLeft, opt.canvas.height - opt.diagramm.marginBottom, opt.canvas.height - opt.diagramm.marginBottom * 2); // Position X & Y , Länge 
			var axisX = new Array(opt.diagramm.marginLeft, opt.canvas.height - opt.diagramm.marginBottom, opt.canvas.width - opt.diagramm.marginLeft); // Position X & Y , Länge
			this._create();
			},
		option: function(option, value){	// übergibt Parameter an Options
			 $.Widget.prototype._setOption.apply( this, arguments );  
			 alert("123");
			 this._create();
		},
		setYscale:function(data, ScaleY, ScaleY_length, axisY, Can){	// Beschreibt die Y-Skala
			var max=0;
			for(i = 0; i < data.length; i++){
				if(data[i] > max)
						max = data[i];
			}		
			axisY_scaling = ScaleY_length/(Math.ceil(max / ScaleY));	// Berechnung der Abstände
			for(i = 0; i <= Math.ceil(max / ScaleY); i++){	// Y Beschriften
				// setze Strich
				Can.font = opt.diagramm.fontSize+"px " + opt.titel.fontFace;	
				Can.moveTo(axisY[0]-2,axisY[1] - (axisY_scaling*i));
				Can.lineTo(axisY[0]+2,axisY[1] - (axisY_scaling*i));
				Can.lineWidth = 2;
				Can.stroke();
				if(i>0)
				Can.fillText(i * ScaleY,opt.diagramm.marginLeft-20,axisY[1]-(axisY_scaling*i)+3);
			}
		},
		
		setXscale: function(data, ScaleX_length, axisX, Can){	// Beschreibt die X-Skala

			axisX_scaling = (Math.floor(ScaleX_length/data.length));	// Berechnung der Abstände

			for(i = 0; i <= data.length; i++){	// Y Beschriften
				// setze Strich
				Can.font = opt.diagramm.fontSize+"px "+opt.diagramm.fontFace;
				Can.moveTo(axisX[0]+axisX_scaling*i,axisX[1]-2);
				Can.lineTo(axisX[0]+axisX_scaling*i,axisX[1]+2);
				Can.lineWidth = 2;
				if(i>0)
					Can.stroke();
				ScaleX_center = axisX_scaling/2;
				// Text mittel setzen 
				if(i!=data.length){
					var center = (axisX_scaling/2)+(data[i].length/2*opt.diagramm.fontSize);
					Can.fillText(data[i],opt.diagramm.marginLeft+((axisX_scaling*(i+1)))-center+14,opt.canvas.height - opt.diagramm.marginBottom + 20);
				}
			}
		},
		
		// Setzt die Datenpunkte
		setDataPoints: function (data, data_name, axisX, axisY, ScaleX_center, ScaleX_length, ScaleY_length, Can){
			axisX_scaling = (Math.floor(ScaleX_length/data.length));
			var max=0;
			for(i = 0; i < data.length; i++){
				if(data[i] > max)
						max = data[i];
			}
			axisY_scaling = ScaleY_length/(Math.ceil(max / opt.diagramm.ScaleY)*opt.diagramm.ScaleY);
			
			var x_alt = axisX[0];
			var y_alt = axisY[1];
			
			for(i = 0 ; i<data_name.length;i++){
				var x = opt.diagramm.marginLeft + (axisX_scaling *(i+1)) - ScaleX_center;
				var y = (opt.canvas.height - opt.diagramm.marginBottom)-(axisY_scaling * data[i]);		
				
				Can.fillStyle = opt.diagramm.color;
				Can.beginPath();
				Can.arc(x, y, 2, 0, Math.PI * 2, true);
				Can.closePath();
				Can.fill();
				Can.stroke();
				
				Can.moveTo(x_alt,y_alt);
				Can.lineTo(x,y);

				Can.lineWidth = 1;
				Can.stroke();
				
				x_alt = x;
				y_alt = y;
			} 
		},
				
		setTitel: function(Can){	// Titel hinzufügen
			// Mittig ausrichten anhand der Breite des Canvas
			var title_center = (opt.canvas.width / 2)-((opt.titel.text.length/2) * opt.titel.fontSize);
			
			// Text in das Canwas schreiben
			
			Can.font = opt.titel.fontSize+"px "+opt.titel.fontFace;	
			Can.fillText(opt.titel.text, title_center , opt.titel.marginTop);
		},

		setDiagramm: function(axisY, axisX, Can){
			
			Can.fillText(0 , opt.diagramm.marginLeft - 10 , opt.canvas.height - opt.diagramm.marginBottom + 10);
			Can.moveTo(axisY[0],axisY[1] + 5);
			Can.lineTo(axisY[0],opt.canvas.height-axisY[1]);
			Can.lineWidth = 2;
			Can.stroke();
			
			Can.moveTo(axisX[0]-5,axisX[1]);
			Can.lineTo(axisX[2],axisX[1]);
			Can.lineWidth = 2;
			Can.stroke();
		},
		
		setCanvas: function(){	// Übergibt Werte an Canvas
			ele.attr("width",opt.canvas.width);
			ele.attr("height",opt.canvas.height);
			ele.css("border",opt.canvas.border);
			ele.css("background-color",opt.canvas.backgroundColor);
		}		

	});
})(jQuery);

Der Gedanke war, das ich das Canvas wieder aufrufe und einfach nur einen Wert neu Übergebe.
$( "#diagramm").diagramm({'canvas':{'backgroundColor':"#CCC"}});
Problem ist jedoch, das ich dadurch eine neue Instanz erzeuge.

Gibt es da einen Trick?

Ich wäre über einen Tipp sehr sehr dankbar.

Lg cRs
 
Hi,

nimm die option-Methode (Zeile 74ff) raus:
Code:
        option: function(option, value){    // übergibt Parameter an Options
             $.Widget.prototype._setOption.apply( this, arguments );  
             alert("123");
             this._create();
        },
In der _setOption-Methode kannst du für gewünschte Optionen spezielle Vorgehensweisen definieren:
Code:
        _setOption: function(option, value){    // übergibt Parameter an Options
            var self = this;

            $.Widget.prototype._setOption.apply( this, arguments );

            switch(option){
            	case 'canvas':
            		console.log("ToDo: Something important when canvas option was updated");
            		self.setCanvas();
            		break;
            }
        },
Im Übrigen kannst du dir immer ansehen, welche Daten das Widget-Objekt enthält. Dazu z.B. in die Konsole folgendes eingeben:
Code:
$( "#diagramm").data('uiDiagramm')
Ciao
Quaese
 
Guten Morgen,

danke erstmal für deine Antwort. Klappt Super.

Ich habe jetzt nur folgendes Problem.

Wenn ich meine Y-Skala anpassen will und $("diagramm") mit ScaleY aufrufe,
dann kennt er die anderen vorgegebenen Werte von option diagramm nicht mehr -.-

Code:
$('form[name="YScale"]').submit(function(){
					$("#diagramm").diagramm(
							{
								"diagramm":
									{"ScaleY":10}
							});
				});

Code:
_setOption: function(option, value){	// übergibt Parameter an Options
			 $.Widget.prototype._setOption.apply( this, arguments );  
			 
			 var self = this;
			 
			 
			 switch(option){
			 	case 'canvas':
			 		console.log("ToDo: Canvas");
			 		self.setCanvas();
			 		break;
			 	case 'diagramm':
			 		var self = this;
					opt = this.options;
					ele = this.element;
			 		console.log("ToDo: Diagramm");
			 		alert(opt.diagramm.color);
			 		this.init();
			 		this.setDiagramm(axisY, axisX,Can)
			 		break;
			 }
        },


init: function(){
			var self = this;
			opt = this.options;
			ele = this.element;
			
			axisY = new Array(opt.diagramm.marginLeft, opt.canvas.height - opt.diagramm.marginBottom, opt.canvas.height - opt.diagramm.marginBottom * 2); // Position X & Y , Länge 
			axisX = new Array(opt.diagramm.marginLeft, opt.canvas.height - opt.diagramm.marginBottom, opt.canvas.width - opt.diagramm.marginLeft); // Position X & Y , Länge
			
			axisX_scaling = (Math.ceil((opt.canvas.width - opt.diagramm.marginLeft * 2) / opt.data.length));	// Berechnung der Abstände
			ScaleX_center = axisX_scaling/2;									// Länge der Skalierung durch 2 (Pro abschnitt)
			ScaleX_center; // Mittelpunkt Skalierung der X - Achse; 

			myCan = document.getElementById(ele.attr('id')); 
			Can = myCan.getContext("2d");
		},


Bei _setOption sind noch paar Test sachen drin.

Danke schonmal

PS: habe gerade festgestellt, das er alle Default werde überschreibt.
Gibt es da einen Trick das zu unterbringen?
 
Zuletzt bearbeitet:
Hi,

der Prototyp aus der jQuery-Widget-Klasse zum Aktualisieren einer Option überschreibt die gewünschte Option lediglich mit der neuen Eigenschaft.
Code:
$.Widget.prototype._setOption.apply( this, arguments );
Das stellt keine Problem dar, solange es sich um "einfache" Datentypen wie Strings oder Zahlen handelt.

Ist die Option, die aktualisiert werden soll, ein Objekt, musst die Vorgehensweise zum Updaten selbst organisiert werden. Bei deinen Optionen canvas und diagramm handelt es sich um Optionen, so dass sich hier die Methode extend anbietet.

Die _setOption-Methode könnte wie folgt aussehen:
Code:
_setOption: function(option, value){    // übergibt Parameter an Options
    var self = this,
        o = self. options;

    switch(option){
    	case 'canvas':
    	    console.log("ToDo: Something important when canvas option was updated");

            // erweitere das bestehende canvas-Objekt um die neuen Eigenschaften
            $.extend(o[option], value);

    	    self.setCanvas();
    	    break;
        case 'diagramm':
            // erweitere das bestehende diagramm-Objekt um die neuen Eigenschaften
            $.extend(o[option], value);

            console.log("ToDo: Anweisungen, die nach dem Aktualisieren der diagramm-Option ausgeführt werden sollen");
            break;
        default:
            $.Widget.prototype._setOption.apply( this, arguments );
    }
}
Die Anweisungen, die nach dem Aktualisieren der "diagramm"-Option ausgeführt werden sollen, musst du noch in das Codefragmet einfügen.

Ciao
Quaese
 
Ich würde dir gern mehr als nur 1 Danke sagen :)

Beschäftige mich erst seit 2 Tagen mit Widget schreiben und seit 1 Woche mit jQuery im allgemeinen.

Sowas findet man leider auch nicht wirklich im Internet, wenn man nicht weiß wonach man 100% sucht.

Zum Glück gibt es aber Menschen wie dich, die einem helfen :)

Danke
 

Neue Beiträge

Zurück