source: trunk/assets/leptonjs/leptonjs.js @ 537

Revision 537, 20.8 KB checked in by noccy, 7 months ago (diff)

Added RGB<->HSV conversion to graphics class (buggy?), made piechart work with actual data sets, and removed buggy elastic code from leptonjs

Line 
1/*
2
3        Lepton/JS - Client Side Library for Lepton
4
5        Licensed under the Gnu Public License (GPL) v2 or later.
6
7        (c) 2009, labs.noccy.com
8        (c) 2008-2009, Christopher Vagnetoft
9
10        For more info see http://labs.noccy.com
11
12*/
13
14var lepton = {
15        version:'0.1'
16};
17
18/******************************************************************************
19 *
20 *   lepton.image
21 *
22 ******************************************************************************/
23
24lepton.Image = {
25        preload:function(src) {
26                if (!(this._images)) this._images = [];
27                var i = new Image();
28                i.src = src;
29                this._images.push(i);
30        }
31};
32
33/******************************************************************************
34 *
35 *   lepton.data
36 *
37 ******************************************************************************/
38
39lepton.data = {};
40
41/**
42 * LeptonJS DataSet: Provides an abstract API to handle, request, and
43 * manipulate data. Initialize the dataset with a provider
44 *
45 *  var oDS = new lepton.data.Dataset();
46 *  oDS.load(new lepton.data.XHRDataProvider('/foo/bar'),{
47 *              onSuccess:function(ds) { dosomethinghere }
48 *  });
49 *
50 *
51 *
52 *
53 */
54lepton.data.Dataset = Class.create({
55        initialize:function(oDataProvider) {
56                if (oDataProvider) this.load(oDataProvider);
57        },
58        load:function(oDataProvider,oArguments) {
59                this._provider = oDataProvider;
60                this._arguments = oArguments;
61                this._provider.bindDataset(this);
62                this._provider.fetch(this.onDataAvailableHandler.bind(this));
63        },
64        onDataAvailableHandler:function() {
65                // When this method is called, we should have the data available in
66                // this._providerso we go ahead and call on the appropriate callback
67                this._arguments.onSuccess(this);
68        }
69});
70
71/**
72 *
73 *
74 */
75lepton.data.GenericProvider = Class.create({
76        bindDataset:function(oDataset) {
77                this._dataset = oDataset;
78        },
79        update:function() { },
80        getDataObject:function() { }
81});
82
83/**
84 *
85 *
86 */
87lepton.data.JSONDataProvider = Class.create(lepton.data.GenericProvider,{
88        initialize:function(sURL) {
89                this._url = sURL;
90        },
91        fetch:function(fCallback) {
92                this._callback = fCallback;
93                // TODO: Do the magic here, and then call on this._dataset.onDataAvailable()
94        }
95});
96
97/**
98 *
99 *
100 */
101lepton.data.CSVDataProvider = Class.create(lepton.data.GenericProvider,{
102        initialize:function(sURL) {
103                this._url = sURL;
104        },
105        fetch:function(fCallback) {
106                this._callback = fCallback;
107                // TODO: Do the magic here, and then call on this._dataset.onDataAvailable()
108        }
109});
110
111/**
112 *
113 *
114 */
115lepton.data.TableDataProvider = Class.create(lepton.data.GenericProvider,{
116        initialize:function(oElem) {
117                this._elem = oElem;
118        },
119        fetch:function(fCallback) {
120                this._callback = fCallback;
121                // TODO: Do the magic here, and then call on this._dataset.onDataAvailable()
122        }
123});
124
125
126/******************************************************************************
127 *
128 *   lepton.forms
129 *
130 ******************************************************************************/
131
132lepton.forms = {};
133
134/**
135 * FormValidation is used to validate a form, and to enable/disable the submit
136 * button based on the forms state.
137 */
138lepton.forms.FormValidation = Class.create({
139        initialize:function(opts) {
140                this._opts = opts || [];
141                this._validators = [];
142        },
143        addValidator:function(validator) {
144                validator.bindForm(this);
145                this._validators.push(validator);
146        },
147        hasValidated:function() {
148                var valid = 0;
149                for (var n = 0; n < this._validators.length; n++) {
150                        if (this._validators[n].isValid()) valid++;
151                }
152                if (valid == this._validators.length) {
153                        if (this._opts.onValid) this._opts.onValid();
154                } else {
155                        if (this._opts.onInvalid) this._opts.onInvalid();
156                }
157        }
158});
159
160/**
161 * This is the template for a validator
162 *
163 */
164lepton.forms.GenericValidator = Class.create({
165        initialize:function(elem,opts) {
166                this._elem = $(elem) || null;
167                if (this._options.validateOnBlur) this._elem.observe('blur',this.validate.bindAsEventListener(this));
168                if (this._options.validateOnChange) this._elem.observe('keyup',this.validate.bindAsEventListener(this));
169                this._valid = this.validate();
170        },
171    /**
172     * Returns true if the value is valid, or false if the value is invalid
173     * @returns (boolean) True if valid
174     */
175    isValid:function() {
176        return(this._valid);
177    },
178        validate:function() {
179                alert('I am validator');
180        },
181        bindForm:function(f) {
182                this._form = f;
183        }
184});
185
186/**
187 *
188 *
189 */
190lepton.forms.StringValidator = Class.create(lepton.forms.GenericValidator,{
191        initialize:function($super,elem,opts) {
192        this._options = Object.extend({
193            required: false,
194            minLength: null,
195            maxLength: null,
196                        match: '',
197            validateOnBlur: true,
198            validateOnChange: false
199        },opts);
200                $super(elem,opts);
201        },
202        validate:function() {
203                var f = this._elem.value;
204                var v = true;
205                if (f == '') {
206                        if (this._options.required) v = false;
207                } else {
208                        if ((this._options.minLength != null) && (f.length < this._options.minLength)) v = false;
209                }
210                this._valid = v;
211                if (this._form) this._form.hasValidated();
212                return;
213        }
214});
215
216/**
217 * Numeric validator, validates a field according to numeric rules.
218 *
219 */
220lepton.forms.NumericValidator = Class.create(lepton.forms.GenericValidator,{
221        initialize:function($super,elem,opts) {
222        // Initialize defaults here
223        this._options = Object.extend({
224            allowNegative: true,
225            required: false,
226            minValue: null,
227            maxValue: null,
228            validateOnBlur: true,
229            validateOnChange: false
230        },opts);
231                $super(elem,opts);
232        }
233});
234
235/**
236 * Ajax validator, performs validation by calling on a server side method
237 *
238 */
239lepton.forms.AjaxValidator = Class.create(lepton.forms.GenericValidator,{
240    initialize:function($super,elem,opts) {
241        this._options = Object.extend({
242                        validateOnBlur: true,
243                        validateOnChange: false,
244                        url: ''
245        },opts);
246        $super(elem,opts);
247    },
248        validate:function() {
249                var params = {};
250                params[this._options.param] = this._elem.value;
251                new Ajax.Request(this._options.url,{
252                        method:'get',
253                        parameters:params,
254                        onSuccess:this._validateCallback.bind(this)
255                });
256        },
257        _validateCallback:function(t) {
258                var r = t.responseText.evalJSON(true);
259                this._valid = (r[this._options.check]);
260                if (this._form) this._form.hasValidated();
261        }
262});
263
264lepton.forms.InlineUpload = Class.create({
265        initialize:function(oForm, oArguments) {
266
267        }
268});
269
270lepton.forms.Editor = Class.create({
271        initialize:function(el,opts) {
272                this._el = $(el);
273                this._opts = opts;
274        },
275        insert:function(before,after) {
276                if (document.selection) {
277                        this._el.focus();
278                        var sr = document.selection.createRange();
279                        sr.text = before + sr.text + after;
280                }
281                else if (this._el.selectionStart || this._el.selectionStart == '0') {
282                        var startPos = this._el.selectionStart;
283                        var endPos = this._el.selectionEnd;
284                        this._el.value = this._el.value.substring(0, startPos)
285                                + before
286                                + this._el.value.substring(startPos, endPos)
287                                + after
288                                + this._el.value.substring(endPos, this._el.value.length);
289                } else {
290                        this._el.value += before + after;
291                }
292                this._el.focus();
293        }
294
295});
296
297
298/******************************************************************************
299 *
300 *   lepton.ui
301 *
302 ******************************************************************************/
303
304lepton.ui = {};
305
306/**
307 *
308 *
309 *
310 */
311lepton.ui.Table = Class.create({
312        initialize:function(elem,oArguments) {
313
314    }
315});
316
317lepton.ui.Tooltip = Class.create({
318        initialize:function(elem,opts) {
319        this._options = Object.extend({
320            opacity: '0.9',
321            backgroundColor: '#FFFFE0',
322                        border: 'solid 1px #404040',
323                        font: '8pt sans-serif',
324                        zIndex: '1999',
325                        padding: '2px',
326                        textColor: '#101010'
327        },opts);
328                this._el = new Element('div');
329                this._el.setStyle({
330                        position:'absolute',
331                        left:'0px',
332                        top:'0px',
333                        display:'none',
334                        padding: this._options.padding,
335                        opacity: this._options.opacity,
336                        backgroundColor: this._options.backgroundColor,
337                        border: this._options.border,
338                        font: this._options.font,
339                        color: this._options.textColor,
340                        zIndex:this._options.zIndex
341                });
342                this._el.update( this._options.text );
343                document.body.appendChild(this._el);
344                if (this._options.bind) {
345                        $(this._options.bind).observe('mouseover', function() { this._el.show(); });
346                        $(this._options.bind).observe('mouseout', function() { this._el.hide(); });
347                }
348    },
349        show:function(elem,text) {
350                if (text) this._el.update(text);
351                if (elem) {
352                        var p = $(elem).cumulativeOffset();
353                        var x = p[0];
354                        var y = p[1] + $(elem).getHeight() + 5;
355                        this._el.setStyle({ left:x+'px', top:y+'px' });
356                }
357                this._el.show();
358        },
359        hide:function() {
360                this._el.hide();
361        }
362});
363
364lepton.ui.tooltip = {
365        show:function(elem,text) {
366                if (lepton.ui.tooltip.instance) delete(lepton.ui.tooltip.instance);
367                lepton.ui.tooltip.instance = new lepton.ui.Tooltip();
368                lepton.ui.tooltip.instance.show(elem,text);
369        },
370        hide:function() {
371                if (lepton.ui.tooltip.instance) {
372                        lepton.ui.tooltip.instance.hide();
373                        delete(lepton.ui.tooltip.instance);
374                }
375        }
376};
377
378lepton.ui.Overlay = Class.create({
379        initialize:function(opts) {
380        this._options = Object.extend({
381            opacity: '0.9',
382            backgroundColor: '#303030',
383                        zIndex: '999'
384        },opts);
385                this.attached = false;
386                this.oElem = new Element('div');
387                this.oElem.setStyle({
388                        position:'fixed',
389                        display:'none',
390                        left:'0px',
391                        top:'0px',
392                        right:'0px',
393                        bottom:'0px',
394                        opacity: this._options.opacity,
395                        backgroundColor: this._options.backgroundColor,
396                        zIndex:this._options.zIndex
397                });
398        },
399        getElement:function() {
400                return this.oElem;
401        },
402        show:function() {
403                if (!this.attached) {
404                        document.documentElement.appendChild(this.oElem);
405                        this.attached=true;
406                }
407                this.oElem.show();
408        },
409        hide:function() {
410                this.oElem.hide();
411        }
412});
413
414lepton.ui.InlineEditor = Class.create({
415        initialize:function(elem,oArguments) {
416                this.oElem = $(elem);
417                this.args = oArguments || {};
418                // hook the element
419                this.oElem.observe("click", this._click.bindAsEventListener(this));
420        },
421        _click:function() {
422
423        }
424});
425
426lepton.ui.Dialog = Class.create({
427        initialize:function(el,opts) {
428                this._el = $(el);
429                this._opts = {
430                        overlay:null
431                };
432                Object.extend(this._opts, opts);
433                this._el.setStyle({
434                        position:'absolute',
435                        zIndex:20000
436                });
437                this._el.addClassName('ljs-ui-dialog');
438                this._el.hide();
439        },
440        show:function() {
441                if (this._opts.overlay) this._opts.overlay.show();
442                this._el.center();
443                this._el.show();
444        },
445        hide:function() {
446                if (this._opts.overlay) this._opts.overlay.hide();
447                this._el.hide();
448        }
449});
450
451lepton.ui.dropmenu = {
452        current: null
453};
454
455lepton.ui.DropMenu = Class.create({
456        initialize:function(el,menu,opts) {
457                this._parent = $(el);
458                if (!this._parent) { return; }
459                this._menu = $(menu);
460                this._opts = opts;
461                this._menu.setStyle({
462                        'position':'absolute',
463                        'display':'none'
464                });
465                this._parent.addClassName('expandable');
466                Event.observe(this._parent,'mouseover',this.showMenu.bindAsEventListener(this));
467                Event.observe(this._parent,'mousemove',this.__cbShow.bindAsEventListener(this));
468                Event.observe(this._parent,'mouseout',this.__cbHide.bindAsEventListener(this));
469        },
470        showMenu:function() {
471                if (lepton.ui.dropmenu.current) {
472                        lepton.ui.dropmenu.current.hideMenu();
473                        lepton.ui.dropmenu.current = null;
474                }
475                if (!this._menu) return;
476                lepton.ui.dropmenu.current = this;
477                this._menu.show();
478                this._state = true;
479                this._parent.addClassName('expanded');
480                var p = this._parent.cumulativeOffset();
481                var x = p[0];
482                var y = p[1] + this._parent.getHeight();
483                this._menu.setStyle({ left:x+'px', top:y+'px' });
484                Event.observe(this._menu,'mousemove',this.__cbShow.bindAsEventListener(this));
485                Event.observe(this._menu,'mouseout',this.__cbHide.bindAsEventListener(this));
486        },
487        hideMenu:function() {
488                this._menu.hide();
489                this._state = false;
490                lepton.ui.dropmenu.current = null;
491                this._parent.removeClassName('expanded');
492                if (this._htimer) clearTimeout(this._htimer);
493        },
494        __refreshTimer:function() {
495                if (this._htimer) clearTimeout(this._htimer);
496                this._htimer = setTimeout(this.__invokeTimer.bindAsEventListener(this),100);
497        },
498        __invokeTimer:function() {
499                if (this._state == false) this.hideMenu();
500        },
501        __cbHide:function() { this._state = false; this.__refreshTimer(); },
502        __cbShow:function() { this._state = true; this.__refreshTimer(); }
503});
504
505lepton.ui.TabBar = Class.create({
506        initialize:function(el,opts) {
507                this._parent = el;
508                this._el = new Element('div');
509                $(this._el).addClassName('ljs-ui-tabbar');
510                $(el).appendChild(this._el);
511        },
512        addButton:function(btn) {
513                btn.attach(this._el);
514        },
515        setActive:function(btnid) {
516                var e = $(this._el).childNodes;
517                for(var n = 0; n < e.length; n++) {
518                        var el = e[n];
519                        if (el.nodeName == 'A') {
520                                if (el.id == btnid) {
521                                        $(el).addClassName('ljs-current');
522                                } else {
523                                        $(el).removeClassName('ljs-current');
524                                }
525                        }
526                }
527        }
528});
529
530lepton.ui.Accordion = Class.create({
531        initialize:function(el,opts) {
532                this._el = $(el);
533                this._pages = [];
534                var e = this._el.childNodes;
535                var i = 0;
536                for(var n = 0; n < e.length; n++) {
537                        var te = e[n];
538                        if (te.nodeName == 'DIV') {
539                                te.addClassName('ljs-accordion-hidden');
540                                te.addClassName('ljs-accordion');
541                                this._pages[i++] = te;
542                        }
543                }
544                this.showPage(0);
545        },
546        showPage:function(index) {
547                for(var n = 0; n < this._pages.length; n++) {
548                        if (n==index) {
549                                this._pages[n].addClassName('ljs-accordion-visible');
550                                this._pages[n].removeClassName('ljs-accordion-hidden');
551                        } else {
552                                this._pages[n].addClassName('ljs-accordion-hidden');
553                                this._pages[n].removeClassName('ljs-accordion-visible');
554                        }
555                }
556        }
557});
558
559lepton.ui.ToolBar = Class.create({
560
561});
562
563lepton.ui.Button = Class.create({
564        initialize:function(opts,cb) {
565                this._el = new Element('a');
566                if (opts.id) $(this._el).id = opts.id;
567                if (opts.hash) $(this._el).href = '#' + opts.hash;
568                $(this._el).addClassName('ljs-ui-button');
569                $(this._el).setStyle({
570                        backgroundImage:'url(' + opts.icon +')'
571                });
572                $(this._el).observe('click', cb);
573        },
574        attach:function(parentel) {
575                parentel.appendChild(this._el);
576        }
577})
578
579/******************************************************************************
580 *
581 *   lepton.ui.bluebox
582 *
583 ******************************************************************************/
584
585/**
586 * This is the BlueBox namespace. Use the setup() method to hook all elements
587 * with the specified class name and turn them into links by creating a new
588 * instance of the bluebox.Image class wrapping it.
589 *
590 * TODO: Make the code respect the tagname - This should only convert A-tags
591 * into clickable thingies.
592 *
593 * @namespace lepton.ui.bluebox
594 *
595 */
596lepton.ui.bluebox = {
597        setup:function(cn,opts) {
598                var els = document.getElementsByClassName(cn);
599                for (var i = 0; i < els.length; i++) {
600                        new lepton.ui.bluebox.Image(els[i],opts);
601                }
602        }
603};
604
605
606/**
607 * The bluebox Image manager. The constructor here hooks the click event for
608 * the anchor, and replaces it with a call to its own showBox() method.
609 *
610 * @namespace lepton.ui.bluebox
611 * @class Image
612 *
613 */
614lepton.ui.bluebox.Image = Class.create({
615        initialize:function(el,opts) {
616                this._el = $(el);
617                this._src = $(el).getAttribute('href');
618                this._opts = {
619                        overlayColor:'#FFFFFF',
620                        overlayOpacity:0.9
621                };
622                Object.extend(this._opts, opts);
623                $(el).observe('click', this.showBox.bindAsEventListener(this));
624        },
625        showBox:function(e) {
626                this._ol = new lepton.ui.Overlay({
627                        backgroundColor:this._opts.overlayColor,
628                        opacity:this._opts.overlayOpacity
629                });
630                this._ol.show();
631                this._pel = new Element('img', { src:this._src } );
632                document.documentElement.appendChild(this._pel);
633                $(this._pel).setStyle({
634                        zIndex:99999,
635                        border:'solid 3px #101010',
636                        position:'absolute',
637                        cursor:'pointer'
638                });
639                $(this._pel).center();
640                $(this._pel).observe('click', this.hideBox.bindAsEventListener(this));
641                Event.stop(e);
642                return false;
643        },
644        hideBox:function() {
645                this._ol.hide();
646                delete this._ol;
647                document.documentElement.removeChild(this._pel);
648                this._pel.hide();
649                delete this._pel;
650        }
651});
652
653
654
655/******************************************************************************
656 *
657 *   lepton.canvas
658 *
659 ******************************************************************************/
660
661lepton.canvas = {};
662lepton.canvas.Color = Class.create({
663        initialize:function(r,g,b,a) {
664                this._r = r;
665                this._g = g;
666                this._b = b;
667                this._a = a;
668        },
669        getRGB:function() {
670                return 'rgb('+this._r+','+this._g+','+this._b+')';
671        },
672        getRGBA:function() {
673                return 'rgba('+this._r+','+this._g+','+this._b+','+this._a+')';
674        }
675});
676
677lepton.Canvas = Class.create({
678        initialize:function(el) {
679                this._cx = $(el).getContext('2d');
680        },
681        drawFilledRect:function(x1,y1,x2,y2,bc,fc) {
682                this._cx.fillStyle = fc;
683                this._cx.lineStyle = bc;
684                this._cx.fillRect(x1,y1,x2,y2);
685        }
686});
687
688
689
690/******************************************************************************
691 *
692 *   lepton.charting
693 *
694 ******************************************************************************/
695
696lepton.charting = {
697    // Chart type constants
698    CHART_TYPE_BAR: 1,
699    CHART_TYPE_LINE: 2,
700    CHART_TYPE_PIE: 3
701};
702
703lepton.charting.Chart = Class.create({ });
704
705lepton.charting.ChartProvider = Class.create({
706    initialize:function() {
707
708    },
709    setChartType:function(eType) {
710        this._type = eType;
711    },
712    setTitle:function(title) {
713        this._title = title;
714    }
715});
716
717lepton.charting.JsCharts = Class.create(lepton.charting.ChartProvider, {
718    initialize:function($super,oArgs) {
719        $super(oArgs);
720    }
721});
722
723
724/******************************************************************************
725 *
726 *   lepton.animation
727 *
728 ******************************************************************************/
729
730lepton.effects = {};
731
732/**
733 * Effect superclass.
734 *
735 */
736lepton.effects.Effect = Class.create({
737    initialize:function(oOpts) {
738        this._elem = $(oOpts.elem);
739        var dim = this._elem.getDimensions();
740        this._width = dim.width;
741        this._height = dim.height;
742    },
743    setOpacity:function(opacity) {
744        this._elem.setOpacity(opacity);
745    }
746});
747
748/**
749 * Fade an element in or out
750 *
751 * oOpts:   element (element) The element to fade
752 *          duration (number) The duration of the effect
753 *          onComplete (function) The onComplete hook
754 *          onBegin (function) The onBegin hook
755 */
756lepton.effects.FadeIn = Class.create(lepton.effects.Effect,{
757    initialize:function($super,oOpts) {
758
759    }
760});
761
762
763
764/******************************************************************************
765 *
766 *   lepton.element
767 *
768 ******************************************************************************/
769
770lepton.Element = {
771    center:function(element) {
772
773        try{
774            element = $(element);
775        }catch(e){
776            return;
777        }
778
779        var my_width  = 0;
780        var my_height = 0;
781
782        if ( typeof( window.innerWidth ) == 'number' ){
783            my_width  = window.innerWidth;
784            my_height = window.innerHeight;
785        } else if ( document.documentElement &&
786                 ( document.documentElement.clientWidth ||
787                   document.documentElement.clientHeight ) ){
788            my_width  = document.documentElement.clientWidth;
789            my_height = document.documentElement.clientHeight;
790        } else if ( document.body &&
791                ( document.body.clientWidth || document.body.clientHeight ) ){
792            my_width  = document.body.clientWidth;
793            my_height = document.body.clientHeight;
794        }
795
796        try {
797            element.style.position = 'absolute';
798            // element.style.zIndex   = 90;
799        } catch(e) { }
800
801        var scrollY = 0;
802
803        if ( document.documentElement && document.documentElement.scrollTop ){
804            scrollY = document.documentElement.scrollTop;
805        } else if ( document.body && document.body.scrollTop ){
806            scrollY = document.body.scrollTop;
807        } else if ( window.pageYOffset ){
808            scrollY = window.pageYOffset;
809        } else if ( window.scrollY ){
810            scrollY = window.scrollY;
811        }
812
813        var elementDimensions = Element.getDimensions(element);
814
815        var setX = ( my_width  - elementDimensions.width  ) / 2;
816        var setY = ( my_height - elementDimensions.height ) / 2 + scrollY;
817
818        setX = ( setX < 0 ) ? 0 : setX;
819        setY = ( setY < 0 ) ? 0 : setY;
820
821        element.style.left = setX + "px";
822        element.style.top  = setY + "px";
823
824        element.style.display  = 'block';
825
826    },
827        loadPage:function(element,url) {
828                new Ajax.Updater(element, url, { method:'get' });
829        },
830        elastic:function(element,maxHeight) {
831                this.maxHeight = maxHeight;
832                $(element).observe('keyup',function() {
833                        var text = $(element);
834                        if ( !text ) return;
835                        var adjustedHeight = text.clientHeight;
836                        if ( !this.maxHeight || this.maxHeight > adjustedHeight ) {
837                                adjustedHeight = Math.max(text.scrollHeight, adjustedHeight);
838                                if ( this.maxHeight )
839                                        adjustedHeight = Math.min(this.maxHeight, adjustedHeight);
840                                if ( adjustedHeight > text.clientHeight )
841                                        text.style.height = (adjustedHeight + 5) + "px";
842                        }
843                });
844                var baseHeight = text.clientHeight;
845                text.style.height = (baseHeight + 5) + "px";
846        }
847}
848
849Element.addMethods(lepton.Element);
Note: See TracBrowser for help on using the repository browser.