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