Merge branch 'master' of git@stigma:platforma
[redakcja.git] / platforma / static / js / views / xml.js
1 /*global View CodeMirror ToolbarView render_template panels */
2 var XMLView = View.extend({
3     _className: 'XMLView',
4     element: null,
5     model: null,
6     template: 'xml-view-template',
7     editor: null,
8     buttonToolbar: null,
9   
10     init: function(element, model, parent, template) {
11         this._super(element, model, template);
12         this.parent = parent;
13         this.buttonToolbar = new ButtonToolbarView(
14             $('.xmlview-toolbar', this.element),
15             this.model.toolbarButtonsModel, parent);
16
17         this.hotkeys = [];
18         var self = this;
19
20         $('.xmlview-toolbar', this.element).bind('resize.xmlview', this.resized.bind(this));
21
22         // scroll to the given position (if availble)
23         this.scrollCallback = this.scrollOnRequest.bind(this);
24         $(document).bind('xml-scroll-request', this.scrollCallback);
25        
26         this.parent.freeze('Ładowanie edytora...');
27
28         setTimeout((function(){
29
30         this.editor = new CodeMirror($('.xmlview', this.element).get(0), {
31             parserfile: 'parsexml.js',
32             path: documentInfo.staticURL + "js/lib/codemirror/",
33             stylesheet: documentInfo.staticURL + "css/xmlcolors.css",
34             parserConfig: {
35                 useHTMLKludges: false
36             },
37             textWrapping: true,
38             tabMode: 'spaces',
39             indentUnit: 0,
40             onChange: this.editorDataChanged.bind(this),
41             initCallback: this.editorDidLoad.bind(this)
42         });
43
44         }).bind(this), 0);
45     },
46   
47     resized: function(event) {
48         var height = this.element.height() - $('.xmlview-toolbar', this.element).outerHeight();
49         $('.xmlview', this.element).height(height);
50     },
51   
52     reload: function() {
53         this.model.load(true);
54     },
55   
56     editorDidLoad: function(editor) {
57         $(editor.frame).css({
58             width: '100%',
59             height: '100%'
60         });
61         this.model
62         .addObserver(this, 'data', this.modelDataChanged.bind(this))
63         .addObserver(this, 'state', this.modelStateChanged.bind(this))
64         .load();           
65       
66         this.editor.setCode(this.model.get('data'));
67         this.modelStateChanged('state', this.model.get('state'));
68         
69         editor.grabKeys(
70             this.hotkeyPressed.bind(this),
71             this.isHotkey.bind(this)
72         );
73
74         this.parent.unfreeze();
75     },
76   
77     editorDataChanged: function() {
78         this.model.set('data', this.editor.getCode());
79     },
80   
81     modelDataChanged: function(property, value) {
82         if (this.editor.getCode() != value) {
83             this.editor.setCode(value);
84         }
85     },
86   
87     modelStateChanged: function(property, value) {
88         if (value == 'synced' || value == 'dirty') {
89             this.unfreeze();
90         } else if (value == 'unsynced') {
91             this.freeze('Niezsynchronizowany...');
92         } else if (value == 'loading') {
93             this.freeze('Ładowanie danych...');
94         } else if (value == 'saving') {
95             this.freeze('Zapisywanie...');
96         } else if (value == 'error') {
97             this.freeze(this.model.get('error'));
98         }
99     },
100     
101     dispose: function() {
102         $(document).unbind('xml-scroll-request', this.scrollCallback);
103         
104         this.model.removeObserver(this);
105         $(this.editor.frame).remove();
106         this._super();
107     },    
108
109     getHotkey: function(event) {
110         var code = event.keyCode;
111         if(!((code >= 97 && code <= 122)
112            || (code >= 65 && code <= 90)) ) return null;
113
114         var ch = String.fromCharCode(code & 0xff).toLowerCase();
115         /* # console.log(ch.charCodeAt(0), '#', buttons); */
116
117         var buttons = $('.buttontoolbarview-button[hotkey='+ch+']', this.element);
118         var mod = 0;
119             
120         if(event.altKey) mod |= 0x01;
121         if(event.ctrlKey) mod |= 0x02;
122         if(event.shiftKey) mod |= 0x04;
123
124         if(buttons.length) {
125             var match = null;
126
127             buttons.each(function() {
128                 if( parseInt($(this).attr('ui:hotkey_mod')) == mod ) {
129                     match = this;
130                     return;
131                 }
132             })
133
134             return match;
135         }
136         else {
137             return null;
138         }
139     },
140
141     isHotkey: function() {
142         /* console.log(arguments); */
143         if(this.getHotkey.apply(this, arguments))
144             return true;
145         else
146             return false;
147     },
148
149     hotkeyPressed: function() {
150         var button = this.getHotkey.apply(this, arguments);
151         this.buttonToolbar.buttonPressed({
152             target: button
153         });
154     },
155
156     scrollOnRequest: function(event, data) 
157     {
158         try {
159             var line = this.editor.nthLine(data.line);
160             this.editor.selectLines(line, (data.column-1));
161         } catch(e) {
162             console.log('Exception in scrollOnRequest:', e);
163         }
164     }
165
166 });
167
168 function Hotkey(code) {
169     this.code = code;
170     this.has_alt = ((code & 0x01 << 8) !== 0);
171     this.has_ctrl = ((code & 0x01 << 9) !== 0);
172     this.has_shift = ((code & 0x01 << 10) !== 0);
173     this.character = String.fromCharCode(code & 0xff);
174 }
175
176 Hotkey.prototype.toString = function() {
177     var mods = [];
178     if(this.has_alt) mods.push('Alt');
179     if(this.has_ctrl) mods.push('Ctrl');
180     if(this.has_shift) mods.push('Shift');
181     mods.push('"'+this.character+'"');
182     return mods.join('+');
183 };
184
185 // Register view
186 panels['xml'] = XMLView;