Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
matrix_insert_link.inc
1 <?php
18 global $ROOT_PATH;
19 include_once($ROOT_PATH.'wysiwyg_plugin.inc');
20 require_once dirname(__FILE__).'/../../../../core/include/init.inc';
21 
34 class matrix_insert_link extends wysiwyg_plugin
35 {
36 
37 
45  function matrix_insert_link(&$wysiwyg)
46  {
47  wysiwyg_plugin::wysiwyg_plugin($wysiwyg);
48  $this->_add_button('matrixcreatelink','MatrixCreateLink', translate('insert_link'),'false','32');
49  $this->_add_button('matrixunlink','Unlink', translate('remove_link'),'false','33');
50 
51  }//end constructor
52 
53 
62  function paint_generic()
63  {
64  ?>
65  <script type="text/javascript" src="<?php echo sq_web_path('lib').'/js/general.js' ?>"></script>
66  <script type="text/javascript" src="<?php echo sq_web_path('fudge').'/var_serialise/var_serialise.js' ?>"></script>
67 
68  <script type="text/javascript" language="Javascript">
69  var wysiwyg_editing = true; // just so that onclick link's don't execute in wysiwyg
70 
71 
72  HTMLArea.prototype._matrixUnLink = function() {
73  var editor = this; // for nested functions
74 
75  var current_a = this.getClosest("a");
76 
77  if (!current_a) {
78  if (HTMLArea.is_ie) { //IMG tag support for IE as they land in controlRange collection.
79  var sel = this._getSelection();
80  var range = this._createRange(sel);
81  if (sel.type == "Control"){
82  for (i = 0; i < range.length; i++){
83  if (range.item(i).tagName == "IMG"){
84  if (range.item(i).parentNode.tagName == "A"){//check parent is anchor
85  current_a = range.item(i).parentNode;
86  break;
87  }
88  }
89  }
90  }
91 
92  }
93  if (!current_a) return false; //still not found
94  }
95  var inside_html = current_a.innerHTML;
96  var selection = editor.getSelectedHTML();
97  //IMG tag support
98  //Firefox: selection same as inside_html but attributes re-arranged.
99  //IE: can't get selection because lands in controlRange collection (see above).
100  //selection only needed to process partial selection so just equate to inside_html (see below).
101  var reg = new RegExp("^\s*<img ?[^>]+src=[^>]+>\s*$", "i");
102  if (!selection || selection.match(reg)) selection = inside_html;
103 
104  // Remove surrounding anchor tag from selected HTML for comparison
105  if (HTMLArea.is_ie) {
106  // Remove anchor start and end
107  var e = '^<a[^>]*>';
108  var re = new RegExp(e, "i");
109  selection = selection.replace(re, "");
110  e = '</a>$';
111  re = new RegExp(e, "i");
112  selection = selection.replace(re, "");
113  // Remove newlines from anchor HTML so we can perform a meaningful comparison
114  e = '\r\n';
115  re = new RegExp(e, "i");
116  selection = selection.replace(re, "");
117  }
118 
119  if (selection != '' && selection != inside_html) {
120  // Partial selection within the link tag
121  // will not work if selection partially includes other tags
122  // for example:
123  // <a href="example.com">partial <b>link</b> here</a>
124  // and user selects "partial <b>li" as the selection
125  var e = '(<a [^>]+>)(.*)' + '(' + selection + ')(.*)(</a>)';
126  var re = new RegExp(e, "i");
127  // turns into "<a>before</a> selection <a>after</a>"
128  var remove_tag = HTMLArea.getHTML(current_a, true).replace(re, "$1$2$5$3$1$4$5");
129  // Remove empty link tags
130  var e = '<a [^>]+>\\s*</a>';
131  var re = new RegExp(e, "gi");
132  inside_html = remove_tag.replace(re, "");
133  }
134  var text = this._doc.createDocumentFragment();
135  var div = this._doc.createElement("div");
136  div.innerHTML = inside_html;
137  while (div.firstChild) {
138  text.appendChild(div.firstChild);
139  }
140  current_a.parentNode.replaceChild(text, current_a);
141  }
142 
143 
144  // Called when the user clicks on "InsertImage" button
145  HTMLArea.prototype._matrixInsertLink = function() {
146  var editor = this; // for nested functions
147 
148  // all available new window options
149  var NEW_WINDOW_OPTIONS = new Array('toolbar','menubar','location','status','scrollbars','resizable','width','height');
150 
151  // OK, let's create the current args array that we'll pass to the dialog
152  var currArgs = new Object();
153  currArgs["assetid"] = "0";
154  currArgs["url"] = "http://";
155  currArgs["class_name"] = "";
156  currArgs["id_name"] = "";
157  currArgs["anchor"] = "";
158  currArgs["status_text"] = "";
159  currArgs["link_title"] = "";
160  currArgs["target"] = "";
161  currArgs["new_window"] = 0;
162  currArgs["show_summary"] = 0;
163 
164  currArgs["new_window_options"] = new Object();
165  for(var i=0; i < NEW_WINDOW_OPTIONS.length; i++) {
166  currArgs["new_window_options"][NEW_WINDOW_OPTIONS[i]] = '';
167  }
168 
169  var sel = this._getSelection();
170  var range = this._createRange(sel);
171  var text_range = false;
172 
173  // OK, so they have a control object selected, let's try and make it a text selection
174  if (sel.type && sel.type.toLowerCase() == "control") {
175  var control_range = this._createRange(sel);
176  var text_range = this._createTextRange(sel);
177  if (text_range != null) {
178  text_range = true;
179  editor.selectNodeContents(control_range(0));
180  } else {
181  alert(js_translate('object_requires_selection'));
182  sel.empty();
183  return;
184  }
185  sel = this._getSelection();
186  range = this._createRange(sel);
187  }// end if a control
188 
189  var inside_html = '';
190  var current_a = this.getClosest("a");
191  if (current_a) {
192  inside_html = current_a.innerHTML;
193  this.selectNodeContents(current_a);
194  } else {
195  inside_html = editor.getSelectedHTML();
196  }
197 
198  sel = this._getSelection();
199  range = this._createRange(sel);
200 
201  // is this aready a link?
202  if (current_a) {
203 
204  var e = '^(<a [^>]+>)(.*)</a>$';
205  var re = new RegExp(e, "i");
206  var tag_html = HTMLArea.getHTML(current_a, true).replace(re, "$1");
207 
208  var re = new RegExp("\n", "gi");
209  var tag_html = tag_html.replace(re, "");
210 
211  currArgs["url"] = current_a.href;
212 
213  re = new RegExp('if \\(!window\\.wysiwyg_editing\\)[\\s]+\\{[\\s]+window\\.open\\([\'"]([^\'"]+)[\'"], [\'"][0-9]+[\'"], [\'"]([^\'"]+)[\'"]\\);', "gi");
214  results = re.exec(tag_html);
215 
216  if (results != null) {
217  currArgs["url"] = results[1];
218  currArgs["new_window"] = 2;
219  var options_str = results[2];
220 
221  for(var i=0; i < NEW_WINDOW_OPTIONS.length; i++) {
222  e = NEW_WINDOW_OPTIONS[i] + "=([^,]+)";
223  re = new RegExp(e, "gi");
224  var res = re.exec(options_str);
225  currArgs["new_window_options"][NEW_WINDOW_OPTIONS[i]] = (res != null) ? res[1] : "";
226  }
227  }// end if
228 
229  // let's try and get the window.status text if any
230  re = new RegExp('onmouseover="([^"]+)"', "gi");
231  results = re.exec(tag_html);
232  if (results != null) {
233  var onmouseover = results[1];
234  re = new RegExp('window.status=\'(.+)\'; return true;', "gi");
235  results = re.exec(onmouseover);
236  if (results != null) {
237  currArgs["status_text"] = rev_htmlspecialchars(results[1]).replace(/\\\'/gi, "\'");
238  }
239  }// end if
240 
241  //Get the link title, if there is one
242  re = new RegExp('title="([^"]+)"', "gi");
243  results = re.exec(tag_html);
244  if (results != null) {
245  currArgs["link_title"] = rev_htmlspecialchars(results[1]);
246  }
247  // let's try and get the target if any
248  re = new RegExp('target="([^"]+)"', "gi");
249  results = re.exec(tag_html);
250  if (results != null) {
251  currArgs["target"] = rev_htmlspecialchars(results[1]).replace(/\\\'/gi, "\'");
252  }
253  if (currArgs["target"] == "_blank") { currArgs["new_window"] = 1; }
254 
255  // let's try and get the class if any
256  re = new RegExp('class="([^"]+)"', "gi");
257  results = re.exec(tag_html);
258  if (results != null) {
259  currArgs["class_name"] = rev_htmlspecialchars(results[1]).replace(/\\\'/gi, "\'");
260  }
261 
262  // let's try and get the class if any
263  re = new RegExp('id="([^"]+)"', "gi");
264  results = re.exec(tag_html);
265  if (results != null) {
266  currArgs["id_name"] = rev_htmlspecialchars(results[1]).replace(/\\\'/gi, "\'");
267  }
268 
269  // it seems that the make_relative_hrefs() fn will take out the hash and think that a lone
270  // anchor is actually the url link. Work out here whether it might need to be added on...
271  var needsHash = false;
272  if (currArgs["url"].indexOf('#') != -1) {
273  needsHash = true;
274  }
275 
276  // because the editor automatically prepend the http:// business to
277  // all relative urls remove it
278  currArgs["url"] = unescape(editor.make_relative_hrefs(currArgs["url"]));
279 
280  // if it's hashed and it's disappeared, add it back on here
281  if (needsHash && (currArgs["url"].indexOf('#') == -1)) {
282  currArgs["url"] = '#' + currArgs["url"];
283  }
284 
285  // get the assetid for the link if there is one
286  // only matches './?a=(normal or shadow id)'
287  e = '\\./\\?a=([0-9]+)((:[^$]*)\\$)?';
288  re = new RegExp(e, "gi");
289  results = re.exec(currArgs["url"]);
290  if (results != null) {
291  currArgs["assetid"] = currArgs["url"].replace(re, "$1$3");
292  }
293 
294 
295  // if the link is made from asset attribute url
296  // make sure to remove the url of it
297  e = '(%globals_asset_attribute_(redirect|link)_url:([0-9]+[^$]+)%)';
298  re = new RegExp(e, "gi");
299  results = re.exec(currArgs["url"]);
300 
301  if (results != null) {
302  currArgs["url"] = results[1];
303  currArgs["assetid"] = results[3];
304  }
305 
306 
307  // else not a link so check for paragraphs
308  } else {
309 
310  // convert all para tags to lowercase
311  var para_html = inside_html.replace(/(<\/?)P/gi, "$1p");
312 
313  // OK so we have some paragraph tags caught up in the mix, let's see what we can do with them
314  // because we don't want our href's going around paragraph tags
315  if (para_html.indexOf("<p") > -1) {
316 
317  // if the position of the first tag is the same as the last then we have only one paragraph
318  // we don't want more than one paragraph because these can start or end from half-way through
319  // a para, which would break the formatting when we go to re-insert the text with the href
320  if (para_html.indexOf("<p") != para_html.lastIndexOf("<p")) {
321  alert(js_translate('select_one_paragraph_at_a_time'));
322  return;
323  }
324 
325  }// end if paragraphs exist
326 
327  // check for multiple list items <li>
328  var para_html = inside_html.replace(/(<\/?)LI/gi, "$1li");
329  if (para_html.indexOf("<li") > -1) {
330  if (para_html.indexOf("<li") != para_html.lastIndexOf("<li")) {
331  alert(js_translate('select_one_list_at_a_time'));
332  return;
333  } else if (para_html.indexOf("</li") > -1) {
334  // we don't want our href's going around a pair of list tags (IE problem)
335  // eg. <a href='url'> <li>item1</li> <li></a>item2</li>
336  alert(js_translate('select_one_list_at_a_time'));
337  return;
338  }
339  }
340 
341  }// end if existing link
342 
343  var in_popup = '0';
344  if (this._inPopup == true) { in_popup = '1'; }
345 
346  editor_<?php echo $this->wysiwyg->name?>._object = this;
347  var strPage = "<?php echo $this->get_popup_href('insert_link_frames.php')?>?assetid=" + escape(currArgs["assetid"]) + "&url=" + escape(currArgs["url"]) + "&status_text=" + escape(currArgs["status_text"]) + "&link_title=" + escape(currArgs["link_title"])+ "&target=" + escape(currArgs["target"]) + "&new_window=" + escape(currArgs["new_window"]) + "&new_window_options=" + escape(var_serialise(currArgs["new_window_options"])) + "&editor_name=" + escape("<?php echo $this->wysiwyg->name; ?>") + "&in_popup=" + escape(in_popup) + "&class_name=" + escape(currArgs["class_name"]) + "&id_name=" + escape(currArgs["id_name"]);;
348 
349  var popup_height = 465;
350 
351  // A bit more breathing room for Safari
352  if (HTMLArea.is_safari) popup_height += 5;
353 
354  // Should we insert the span wrapping around the asset summary?
355  // Avoid inserting it repeatedly
356  var insert_asset_summary_span = true;
357  if(current_a) {
358  var parent = current_a.parentNode;
359  if(parent) {
360  if(parent.nodeName == 'SPAN' && parent.className == 'include_asset_summary') {
361  if(editor.getSelectedHTML().match(/<span class="?include_asset_summary"?>/gi) == null) {
362  insert_asset_summary_span = false;
363  }
364  }
365  }
366  }
367 
368 
369  this._popupDialog("matrixInsertLink", strPage, 750, popup_height, true, function(param) {
370  if (param && param["url"] != "") {
371 
372  var html = '';
373 
374  // if we have an advanced new window, generate the new javascript url string
375  if (param["new_window"] == "1") { param["target"] = "_blank"; }
376  if (param["new_window"] == "2") {
377  var now = new Date();
378  var option_string = "";
379  for(var i=0; i < NEW_WINDOW_OPTIONS.length; i++) {
380  if (option_string != "") option_string += ",";
381  option_string += NEW_WINDOW_OPTIONS[i] + "=" + param["new_window_options"][NEW_WINDOW_OPTIONS[i]];
382  }
383 
384  param["onClick"] = "javascript: if (!window.wysiwyg_editing) { window.open('" + param["url"] + "', '" + now.getTime() + "', '" + option_string + "'); } return false;";
385  param["target"] = "";
386  }
387 
388  // This fixes some probs IE has with Paragraphs
389  var lower_range = '';
390  if (HTMLArea.is_ie) {
391  lower_range = range.htmlText;
392  lower_range = lower_range.replace(/(<\/?)P/gi, "$1p");
393  lower_range = lower_range.substring(0, lower_range.indexOf('</p>') + 4);
394  }
395 
396  if (HTMLArea.is_ie && lower_range.indexOf('<p') != -1) {
397  //See bug #987 for details on why this is done
398  //It avoids <a> tags outside <p> tags
399  var start_new = lower_range.substring(0, lower_range.indexOf('>') + 1);
400  var end_new = lower_range.substring(lower_range.lastIndexOf('<'));
401  var new_middle = lower_range.substring(start_new.length, lower_range.length - end_new.length);
402  html = '<a href="' + param["url"] + '"';
403  if (param["class_name"] != "") {
404  html += ' class="' + htmlspecialchars(param["class_name"]).replace(/\'/gi, "\\'") + '"';
405  }
406  if (param["id_name"] != "") {
407  html += ' id="' + htmlspecialchars(param["id_name"]).replace(/\'/gi, "\\'") + '"';
408  }
409  if (param["target"] != "") {
410  html += ' target="' + htmlspecialchars(param["target"]).replace(/\'/gi, "\\'") + '"';
411  }
412  if (param["status_text"] != "") {
413  html += ' onMouseOver="javascript: window.status=\'' + htmlspecialchars(param["status_text"]).replace(/\'/gi, "\\'") + '\'; return true;" onMouseOut="javascript: window.status=\'\'; return true;"';
414  }
415  if (param["link_title"] != "") {
416  html += ' title="' + htmlspecialchars(param["link_title"]) + '"';
417  }
418  if (param["onClick"] != null && param["onClick"] != "") {
419  html += ' onClick="' + param["onClick"] + '"';
420  }
421 
422 
423  // insert file summary keyword
424  new_middle = new_middle.replace(/%asset_summary_[0-9]+%/gim, '');
425 
426  if (param['show_summary'] && param['assetid']) {
427  html += '>' + new_middle + "%asset_summary_" + param['assetid'] + "%" + '</a>';
428  if (insert_asset_summary_span) {
429  html = '<span class="include_asset_summary">' + html + '</span>';
430  }
431  }
432  else {
433  html += '>' + new_middle + '</a>';
434  }
435 
436  editor.insertHTML('', range);
437  editor.insertHTML(start_new + html + end_new);
438  } else {
439  //We don't have IE, or there is no paragraph present to warrant different handling
440  html += '<a href="' + param["url"] + '"';
441  if (param["class_name"] != "") {
442  html += ' class="' + htmlspecialchars(param["class_name"]).replace(/\'/gi, "\\'") + '"';
443  }
444  if (param["id_name"] != "") {
445  html += ' id="' + htmlspecialchars(param["id_name"]).replace(/\'/gi, "\\'") + '"';
446  }
447  if (param["target"] != "") {
448  html += ' target="' + htmlspecialchars(param["target"]).replace(/\'/gi, "\\'") + '"';
449  }
450  if (param["status_text"] != "") {
451  html += ' onMouseOver="javascript: window.status=\'' + htmlspecialchars(param["status_text"]).replace(/\'/gi, "\\'") + '\'; return true;" onMouseOut="javascript: window.status=\'\'; return true;"';
452  }
453  if (param["link_title"] != "") {
454  html += ' title="' + htmlspecialchars(param["link_title"]) + '"';
455  }
456  if (param["onClick"] != null && param["onClick"] != "") {
457  html += ' onClick="' + param["onClick"] + '"';
458  }
459 
460 
461 
462  // remove existing link(s) before inserting a new link
463  if (current_a) {
464  current_a.parentNode.removeChild(current_a);
465  } else {
466  // overlap/partially overlap (existing links)
467  // note: regex doesn't work on nested tags, like in '<a>one<a>two</a>one</a>'
468  var e = '<a[^>]*>(.*?)</a>';
469  var re = new RegExp(e, "gim");
470  inside_html = inside_html.replace(re, "$1");
471  }
472 
473 
474 
475  // insert file summary keyword
476  inside_html = inside_html.replace(/%asset_summary_[0-9]+%/gim, '');
477  if (param['show_summary'] && param['assetid']) {
478  html += '>' + inside_html + "%asset_summary_" + param['assetid'] + "%" + '</a>';
479  if (insert_asset_summary_span) {
480  html = '<span class="include_asset_summary">' + html + '</span>';
481  }
482  }
483  else {
484  html += '>' + inside_html + '</a>';
485  }
486 
487  html = editor.make_absolute_urls(html);
488 
489  // replace with new URL
490  editor.insertHTML(html, range);
491  }
492 
493 
494  }// end if param exists
495 
496  }, null);
497 
498  };
499  </script>
500  <?php
501 
502  }//end paint_generic()
503 
504 
511  function print_plugin_shortcuts()
512  {
513  ?>
514  case 'k':
515  this._matrixInsertLink();
516  HTMLArea._stopEvent(ev);
517  break;
518  <?php
519 
520  }//end print_plugin_shortcuts()
521 
522 
529  function print_plugin_button_click()
530  {
531  ?>
532  case "matrixcreatelink":
533  this._matrixInsertLink();
534  break;
535  case "unlink":
536  this._matrixUnLink();
537  break;
538  <?php
539 
540  }//end print_plugin_button_click()
541 
542 
549  function print_plugin_update_toolbar()
550  {
551  ?>
552  case "matrixcreatelink":
553  if (allEnabled == null && this._tmp['disable_toolbar'] == true) {
554  this.updateToolbar(false);
555  return;
556  }
557  break;
558  <?php
559 
560  }//end print_plugin_update_toolbar()
561 
562 
563 }//end class
564 
565 ?>