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

Last change on this file since 41 was 41, checked in by gogo, 14 years ago

Applying #66

  • Property svn:eol-style set to native
  • Property svn:keywords set to LastChangedDate LastChangedRevision LastChangedBy HeadURL Id
File size: 11.5 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) { lDialog.files = eval(txt); lDialog._prepareDialog(); });
319    }
320    else if(linker.lConfig.files != null)
321    {
322        //get files from plugin-config
323        lDialog.files = linker.lConfig.files;
324        lDialog._prepareDialog();
325    }
326    return;
327  }
328  var files = this.files;
329
330  if(this.html == false)
331  {
332    HTMLArea._getback(_editor_url + 'plugins/Linker/dialog.html', function(txt) { lDialog.html = txt; lDialog._prepareDialog(); });
333    return;
334  }
335  var html = this.html;
336
337  // Now we have everything we need, so we can build the dialog.
338  var dialog = this.dialog = new HTMLArea.Dialog(linker.editor, this.html, 'Linker');
339  var dTreeName = HTMLArea.uniq('dTree_');
340
341  this.dTree = new dTree(dTreeName, _editor_url + 'plugins/Linker/dTree/');
342  eval(dTreeName + ' = this.dTree');
343
344  this.dTree.add(this.Dialog_nxtid++, -1, document.location.host, null, document.location.host);
345  this.makeNodes(files, 0);
346
347  // Put it in
348  var ddTree = this.dialog.getElementById('dTree');
349  //ddTree.innerHTML = this.dTree.toString();
350  ddTree.innerHTML = '';
351  ddTree.style.position = 'absolute';
352  ddTree.style.left = 1 + 'px';
353  ddTree.style.top =  0 + 'px';
354  ddTree.style.overflow = 'auto';
355  this.ddTree = ddTree;
356  this.dTree._linker_premade = this.dTree.toString();
357
358  var options = this.dialog.getElementById('options');
359  options.style.position = 'absolute';
360  options.style.top      = 0   + 'px';
361  options.style.right    = 0   + 'px';
362  options.style.width    = 320 + 'px';
363  options.style.overflow = 'auto';
364
365  // Hookup the resizer
366  this.dialog.onresize = function()
367    {
368      options.style.height = ddTree.style.height = (dialog.height - dialog.getElementById('h1').offsetHeight) + 'px';
369      ddTree.style.width  = (dialog.width  - 322 ) + 'px';
370    }
371
372  this.ready = true;
373}
374
375Linker.Dialog.prototype.makeNodes = function(files, parent)
376{
377  for(var i = 0; i < files.length; i++)
378  {
379    if(typeof files[i] == 'string')
380    {
381      this.dTree.add(Linker.nxtid++, parent,
382                     files[i].replace(/^.*\//, ''),
383                     '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);',
384                     files[i]);
385    }
386    else
387    {
388      var id = this.Dialog_nxtid++;
389      this.dTree.add(id, parent, files[i][0].replace(/^.*\//, ''), null, files[i][0]);
390      this.makeNodes(files[i][1], id);
391    }
392  }
393}
394
395Linker.Dialog.prototype._lc = Linker.prototype._lc;
396
397Linker.Dialog.prototype.show = function(inputs, ok, cancel)
398{
399  if(!this.ready)
400  {
401    var lDialog = this;
402    window.setTimeout(function() {lDialog.show(inputs,ok,cancel);},100);
403    return;
404  }
405
406  if(this.ddTree.innerHTML == '')
407  {
408    this.ddTree.innerHTML = this.dTree._linker_premade;
409  }
410
411  if(inputs.type=='url')
412  {
413    this.dialog.getElementById('urltable').style.display = '';
414    this.dialog.getElementById('mailtable').style.display = 'none';
415  }
416  else
417  {
418    this.dialog.getElementById('urltable').style.display = 'none';
419    this.dialog.getElementById('mailtable').style.display = '';
420  }
421
422  if(inputs.target=='popup')
423  {
424    this.dialog.getElementById('popuptable').style.display = '';
425  }
426  else
427  {
428    this.dialog.getElementById('popuptable').style.display = 'none';
429  }
430
431  // Connect the OK and Cancel buttons
432  var dialog = this.dialog;
433  var lDialog = this;
434  if(ok)
435  {
436    this.dialog.getElementById('ok').onclick = ok;
437  }
438  else
439  {
440    this.dialog.getElementById('ok').onclick = function() {lDialog.hide();};
441  }
442
443  if(cancel)
444  {
445    this.dialog.getElementById('cancel').onclick = cancel;
446  }
447  else
448  {
449    this.dialog.getElementById('cancel').onclick = function() { lDialog.hide()};
450  }
451
452  // Show the dialog
453  this.linker.editor.disableToolbar(['fullscreen','linker']);
454
455  this.dialog.show(inputs);
456
457  // Init the sizes
458  this.dialog.onresize();
459}
460
461Linker.Dialog.prototype.hide = function()
462{
463  this.linker.editor.enableToolbar();
464  return this.dialog.hide();
465}
466
Note: See TracBrowser for help on using the repository browser.