source: trunk/plugins/Linker/linker.js @ 57

Last change on this file since 57 was 57, checked in by niko, 14 years ago

ticket #67:

  • label for files using the syntax suggested by gogo
  • updated scan.php to use the new syntax

ticket #99:

  • Property svn:eol-style set to native
  • Property svn:keywords set to LastChangedDate LastChangedRevision LastChangedBy HeadURL Id
File size: 12.6 KB
Line 
1/** htmlArea - James' Fork - Linker Plugin **/
2Linker._pluginInfo =
3{
4  name     : "Linker",
5  version  : "1.0",
6  developer: "James Sleeman",
7  developer_url: "http://www.gogo.co.nz/",
8  c_owner      : "Gogo Internet Services",
9  license      : "htmlArea",
10  sponsor      : "Gogo Internet Services",
11  sponsor_url  : "http://www.gogo.co.nz/"
12};
13
14HTMLArea.loadStyle('dTree/dtree.css', 'Linker');
15
16HTMLArea.Config.prototype.Linker =
17{
18  'backend' : _editor_url + 'plugins/Linker/scan.php',
19  'files' : null
20}
21
22
23function Linker(editor, args)
24{
25  this.editor  = editor;
26  this.lConfig = editor.config.Linker;
27
28  var linker = this;
29  if(editor.config.btnList.createlink)
30  {
31    editor.config.btnList.createlink[3]
32      =  function(e, objname, obj) { linker._createLink(linker._getSelectedAnchor()); };
33  }
34  else
35  {
36    editor.config.registerButton(
37                                 'createlink', 'Insert/Modify Hyperlink', [_editor_url + "images/ed_buttons_main.gif",6,1], false,
38                                 function(e, objname, obj) { linker._createLink(linker._getSelectedAnchor()); }
39                                 );
40  }
41
42  // See if we can find 'createlink'
43  var t = editor.config.toolbar;
44  var done = false;
45  for(var i = 0; i < t.length && !done; i++)
46  {
47    for(var x = 0; x < t[i].length && !done; x++)
48    {
49      if(t[i][x] == 'createlink')
50      {
51        done = true;
52      }
53    }
54  }
55
56  if(!done)
57  {
58    t[t.length-1].push('createlink');
59  }
60}
61
62Linker.prototype._lc = function(string)
63{
64  return HTMLArea._lc(string, 'Linker');
65}
66
67Linker.prototype._createLink = function(a)
68{
69  if(!a && this.editor._selectionEmpty(this.editor._getSelection()))
70  {       
71    alert(this._lc("You must select some text before making a new link."));
72    return false;
73  }
74
75  var inputs =
76  {
77    type:     'url',
78    href:     'http://www.example.com/',
79    target:   '',
80    p_width:  '',
81    p_height: '',
82    p_options: ['menubar=no','toolbar=yes','location=no','status=no','scrollbars=yes','resizeable=yes'],
83    to:       'alice@example.com',
84    subject:  '',
85    body:     ''
86  }
87
88  if(a && a.tagName.toLowerCase() == 'a')
89  {
90    var m = a.href.match(/^mailto:(.*@[^?&]*)(\?(.*))?$/);
91    if(m)
92    {
93      // Mailto
94      inputs.type = 'mailto';
95      inputs.to = m[1];
96      if(m[3])
97      {
98        var args  = m[3].split('&');
99        for(var x = 0; x<args.length; x++)
100        {
101          var j = args[x].match(/(subject|body)=(.*)/);
102          if(j)
103          {
104            inputs[j[1]] = decodeURIComponent(j[2]);
105          }
106        }
107      }
108    }
109    else
110    {
111
112
113      if(a.getAttribute('onclick'))
114      {
115        var m = a.getAttribute('onclick').match(/window\.open\(\s*this\.href\s*,\s*'([a-z0-9_]*)'\s*,\s*'([a-z0-9_=,]*)'\s*\)/i);
116
117        // Popup Window
118        inputs.href   = a.href ? a.href : '';
119        inputs.target = 'popup';
120        inputs.p_name = m[1];
121        inputs.p_options = [ ];
122
123
124        var args = m[2].split(',');
125        for(var x = 0; x < args.length; x++)
126        {
127          var i = args[x].match(/(width|height)=([0-9]+)/);
128          if(i)
129          {
130            inputs['p_' + i[1]] = parseInt(i[2]);
131          }
132          else
133          {
134            inputs.p_options.push(args[x]);
135          }
136        }
137      }
138      else
139      {
140        // Normal
141        inputs.href   = a.href;
142        inputs.target = a.target;
143      }
144    }
145  }
146
147  var linker = this;
148
149  // If we are not editing a link, then we need to insert links now using execCommand
150  // because for some reason IE is losing the selection between now and when doOK is
151  // complete.  I guess because we are defocusing the iframe when we click stuff in the
152  // linker dialog.
153
154  this.a = a; // Why doesn't a get into the closure below, but if I set it as a property then it's fine?
155
156  var doOK = function()
157  {
158    //if(linker.a) alert(linker.a.tagName);
159    var a = linker.a;
160
161    var values = linker._dialog.hide();
162    var atr =
163    {
164      href: '',
165      target:'',
166      title:'',
167      onclick:''
168    }
169
170    if(values.type == 'url')
171    {
172     if(values.href)
173     {
174       atr.href = values.href;
175       atr.target = values.target;
176       if(values.target == 'popup')
177       {
178
179         if(values.p_width)
180         {
181           values.p_options.push('width=' + values.p_width);
182         }
183         if(values.p_height)
184         {
185           values.p_options.push('height=' + values.p_height);
186         }
187         atr.onclick = 'try{if(document.designMode && document.designMode == \'on\') return false;}catch(e){} window.open(this.href, \'' + (values.p_name.replace(/[^a-z0-9_]/i, '_')) + '\', \'' + values.p_options.join(',') + '\');return false;';
188       }
189     }
190    }
191    else
192    {
193      if(values.to)
194      {
195        atr.href = 'mailto:' + values.to + '?';
196        if(values.subject) atr.href += 'subject=' + encodeURIComponent(values.subject);
197        if(values.body)    atr.href += (values.subject ? '&' : '') + 'body=' + encodeURIComponent(values.body);
198      }
199    }
200
201    if(a && a.tagName.toLowerCase() == 'a')
202    {
203      if(!atr.href)
204      {
205        if(confirm(linker._dialog._lc('Are you sure you wish to remove this link?')))
206        {
207          var p = a.parentNode;
208          while(a.hasChildNodes())
209          {
210            p.insertBefore(a.removeChild(a.childNodes[0]), a);
211          }
212          p.removeChild(a);
213        }
214      }
215      // Update the link
216      for(var i in atr)
217      {
218        a.setAttribute(i, atr[i]);
219      }
220    }
221    else
222    {
223      if(!atr.href) return true;
224
225      // Insert a link, we let the browser do this, we figure it knows best
226      var tmp = HTMLArea.uniq('http://www.example.com/Link');
227      linker.editor._doc.execCommand('createlink', false, tmp);
228
229      // Fix them up
230      var anchors = linker.editor._doc.getElementsByTagName('a');
231      for(var i = 0; i < anchors.length; i++)
232      {
233        var a = anchors[i];
234        if(a.href == tmp)
235        {
236          // Found one.
237          for(var i in atr)
238          {
239            a.setAttribute(i, atr[i]);
240          }
241        }
242      }
243    }
244  }
245
246  this._dialog.show(inputs, doOK);
247
248}
249
250Linker.prototype._getSelectedAnchor = function()
251{
252  var sel  = this.editor._getSelection();
253  var rng  = this.editor._createRange(sel);
254  var a    = this.editor._activeElement(sel);
255  if(a != null && a.tagName.toLowerCase() == 'a')
256  {
257    return a;
258  }
259  else
260  {
261    a = this.editor._getFirstAncestor(sel, 'a');
262    if(a != null)
263    {
264      return a;
265    }
266  }
267  return null;
268}
269
270Linker.prototype.onGenerate = function()
271{
272  this._dialog = new Linker.Dialog(this);
273}
274// Inline Dialog for Linker
275
276Linker.Dialog_dTrees = [ ];
277
278
279Linker.Dialog = function (linker)
280{
281  var  lDialog = this;
282  this.Dialog_nxtid = 0;
283  this.linker = linker;
284  this.id = { }; // This will be filled below with a replace, nifty
285
286  this.ready = false;
287  this.files  = false;
288  this.html   = false;
289  this.dialog = false;
290
291  // load the dTree script
292  this._prepareDialog();
293
294}
295
296Linker.Dialog.prototype._prepareDialog = function()
297{
298  var lDialog = this;
299  var linker = this.linker;
300
301  // We load some stuff up int he background, recalling this function
302  // when they have loaded.  This is to keep the editor responsive while
303  // we prepare the dialog.
304  if(typeof dTree == 'undefined')
305  {
306    HTMLArea._loadback(_editor_url + 'plugins/Linker/dTree/dtree.js',
307                       function() {lDialog._prepareDialog(); }
308                      );
309    return;
310  }
311
312  if(this.files == false)
313  {
314    if(linker.lConfig.backend)
315    {
316        //get files from backend
317        HTMLArea._getback(linker.lConfig.backend,
318                          function(txt) {
319                            try {
320                                eval('lDialog.files = '+txt);
321                            } catch(Error) {
322                                lDialog.files = [ {url:'',title:Error.toString()} ];
323                            }
324                            lDialog._prepareDialog(); });
325    }
326    else if(linker.lConfig.files != null)
327    {
328        //get files from plugin-config
329        lDialog.files = linker.lConfig.files;
330        lDialog._prepareDialog();
331    }
332    return;
333  }
334  var files = this.files;
335
336  if(this.html == false)
337  {
338    HTMLArea._getback(_editor_url + 'plugins/Linker/dialog.html', function(txt) { lDialog.html = txt; lDialog._prepareDialog(); });
339    return;
340  }
341  var html = this.html;
342
343  // Now we have everything we need, so we can build the dialog.
344  var dialog = this.dialog = new HTMLArea.Dialog(linker.editor, this.html, 'Linker');
345  var dTreeName = HTMLArea.uniq('dTree_');
346
347  this.dTree = new dTree(dTreeName, _editor_url + 'plugins/Linker/dTree/');
348  eval(dTreeName + ' = this.dTree');
349
350  this.dTree.add(this.Dialog_nxtid++, -1, document.location.host, null, document.location.host);
351  this.makeNodes(files, 0);
352
353  // Put it in
354  var ddTree = this.dialog.getElementById('dTree');
355  //ddTree.innerHTML = this.dTree.toString();
356  ddTree.innerHTML = '';
357  ddTree.style.position = 'absolute';
358  ddTree.style.left = 1 + 'px';
359  ddTree.style.top =  0 + 'px';
360  ddTree.style.overflow = 'auto';
361  this.ddTree = ddTree;
362  this.dTree._linker_premade = this.dTree.toString();
363
364  var options = this.dialog.getElementById('options');
365  options.style.position = 'absolute';
366  options.style.top      = 0   + 'px';
367  options.style.right    = 0   + 'px';
368  options.style.width    = 320 + 'px';
369  options.style.overflow = 'auto';
370
371  // Hookup the resizer
372  this.dialog.onresize = function()
373    {
374      options.style.height = ddTree.style.height = (dialog.height - dialog.getElementById('h1').offsetHeight) + 'px';
375      ddTree.style.width  = (dialog.width  - 322 ) + 'px';
376    }
377
378  this.ready = true;
379}
380
381Linker.Dialog.prototype.makeNodes = function(files, parent)
382{
383  for(var i = 0; i < files.length; i++)
384  {
385    if(typeof files[i] == 'string')
386    {
387      this.dTree.add(Linker.nxtid++, parent,
388                     files[i].replace(/^.*\//, ''),
389                     'javascript:document.getElementsByName(\'' + this.dialog.id.href + '\')[0].value=decodeURIComponent(\'' + encodeURIComponent(files[i]) + '\');document.getElementsByName(\'' + this.dialog.id.type + '\')[0].click();document.getElementsByName(\'' + this.dialog.id.href + '\')[0].focus();void(0);',
390                     files[i]);
391    }
392    else if(files[i].length)
393    {
394      var id = this.Dialog_nxtid++;
395      this.dTree.add(id, parent, files[i][0].replace(/^.*\//, ''), null, files[i][0]);
396      this.makeNodes(files[i][1], id);
397    }
398    else if(typeof files[i] == 'object')
399    {
400      if(files[i].children) {
401        var id = this.Dialog_nxtid++;
402      } else {
403        var id = Linker.nxtid++;
404      }
405
406      if(files[i].title) var title = files[i].title;
407      else if(files[i].url) var title = files[i].url.replace(/^.*\//, '');
408      else var title = "no title defined";
409      if(files[i].url) var link = 'javascript:document.getElementsByName(\'' + this.dialog.id.href + '\')[0].value=decodeURIComponent(\'' + encodeURIComponent(files[i].url) + '\');document.getElementsByName(\'' + this.dialog.id.type + '\')[0].click();document.getElementsByName(\'' + this.dialog.id.href + '\')[0].focus();void(0);';
410      else var link = '';
411     
412      this.dTree.add(id, parent, title, link, title);
413      if(files[i].children) {
414        this.makeNodes(files[i].children, id);
415      }
416    }
417  }
418}
419
420Linker.Dialog.prototype._lc = Linker.prototype._lc;
421
422Linker.Dialog.prototype.show = function(inputs, ok, cancel)
423{
424  if(!this.ready)
425  {
426    var lDialog = this;
427    window.setTimeout(function() {lDialog.show(inputs,ok,cancel);},100);
428    return;
429  }
430
431  if(this.ddTree.innerHTML == '')
432  {
433    this.ddTree.innerHTML = this.dTree._linker_premade;
434  }
435
436  if(inputs.type=='url')
437  {
438    this.dialog.getElementById('urltable').style.display = '';
439    this.dialog.getElementById('mailtable').style.display = 'none';
440  }
441  else
442  {
443    this.dialog.getElementById('urltable').style.display = 'none';
444    this.dialog.getElementById('mailtable').style.display = '';
445  }
446
447  if(inputs.target=='popup')
448  {
449    this.dialog.getElementById('popuptable').style.display = '';
450  }
451  else
452  {
453    this.dialog.getElementById('popuptable').style.display = 'none';
454  }
455
456  // Connect the OK and Cancel buttons
457  var dialog = this.dialog;
458  var lDialog = this;
459  if(ok)
460  {
461    this.dialog.getElementById('ok').onclick = ok;
462  }
463  else
464  {
465    this.dialog.getElementById('ok').onclick = function() {lDialog.hide();};
466  }
467
468  if(cancel)
469  {
470    this.dialog.getElementById('cancel').onclick = cancel;
471  }
472  else
473  {
474    this.dialog.getElementById('cancel').onclick = function() { lDialog.hide()};
475  }
476
477  // Show the dialog
478  this.linker.editor.disableToolbar(['fullscreen','linker']);
479
480  this.dialog.show(inputs);
481
482  // Init the sizes
483  this.dialog.onresize();
484}
485
486Linker.Dialog.prototype.hide = function()
487{
488  this.linker.editor.enableToolbar();
489  return this.dialog.hide();
490}
491
Note: See TracBrowser for help on using the repository browser.