devel_themer.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. (function ($) {
  2. $(document).ready(function () {
  3. lastObj = false;
  4. thmrSpanified = false;
  5. strs = Drupal.settings.thmrStrings;
  6. $('body').addClass("thmr_call").attr("id", "thmr_" + Drupal.settings.page_id);
  7. $('[thmr]')
  8. .hover(
  9. function () {
  10. if (themerEnabled && this.parentNode.nodeName != 'BODY' && $(this).attr('thmr_curr') != 1) {
  11. $(this).css('outline', 'red solid 1px');
  12. }
  13. },
  14. function () {
  15. if (themerEnabled && $(this).attr('thmr_curr') != 1) {
  16. $(this).css('outline', 'none');
  17. }
  18. }
  19. );
  20. var themerEnabled = 0;
  21. var themerToggle = function () {
  22. themerEnabled = 1 - themerEnabled;
  23. $('#themer-toggle :checkbox').attr('checked', themerEnabled ? 'checked' : '');
  24. $('#themer-popup').css('display', themerEnabled ? 'block' : 'none');
  25. if (themerEnabled) {
  26. document.onclick = themerEvent;
  27. if (lastObj != false) {
  28. $(lastObj).css('outline', '3px solid #999');
  29. }
  30. if (!thmrSpanified) {
  31. spanify();
  32. }
  33. }
  34. else {
  35. document.onclick = null;
  36. if (lastObj != false) {
  37. $(lastObj).css('outline', 'none');
  38. }
  39. }
  40. };
  41. $(Drupal.settings.thmr_popup)
  42. .appendTo($('body'));
  43. $('<div id="themer-toggle"><input type="checkbox" />'+ strs.themer_info +'</div>')
  44. .appendTo($('body'))
  45. .click(themerToggle);
  46. $('#themer-popup').resizable();
  47. $('#themer-popup')
  48. .draggable({
  49. opacity: .6,
  50. handle: $('#themer-popup .topper')
  51. })
  52. .prepend(strs.toggle_throbber)
  53. ;
  54. // close box
  55. $('#themer-popup .topper .close').click(function() {
  56. themerToggle();
  57. });
  58. });
  59. /**
  60. * Known issue: IE does NOT support outline css property.
  61. * Solution: use another browser
  62. */
  63. function themerHilight(obj) {
  64. // hilight the current object (and un-highlight the last)
  65. if (lastObj != false) {
  66. $(lastObj).css('outline', 'none').attr('thmr_curr', 0);
  67. }
  68. $(obj).css('outline', '#999 solid 3px').attr('thmr_curr', 1);
  69. lastObj = obj;
  70. }
  71. function themerDoIt(obj) {
  72. if (thmrInPop(obj)) {
  73. return true;
  74. }
  75. // start throbber
  76. //$('#themer-popup img.throbber').show();
  77. var objs = thmrFindParents(obj);
  78. if (objs.length) {
  79. themerHilight(objs[0]);
  80. thmrRebuildPopup(objs);
  81. }
  82. return false;
  83. }
  84. function spanify() {
  85. $('span[thmr]')
  86. .each(function () {
  87. // make spans around block elements into block elements themselves
  88. var kids = $(this).children();
  89. for(i=0;i<kids.length;i++) {
  90. //console.log(kids[i].style.display);
  91. if ($(kids[i]).css('display') != 'inline' && $(kids[i]).is('DIV, P, ADDRESS, BLOCKQUOTE, CENTER, DIR, DL, FIELDSET, FORM, H1, H2, H3, H4, H5, H6, HR, ISINDEX, MENU, NOFRAMES, NOSCRIPT, OL, PRE, TABLE, UL, DD, DT, FRAMESET, LI, TBODY, TD, TFOOT, TH, THEAD, TR')) {
  92. $(this).css('display', 'block');
  93. }
  94. }
  95. });
  96. thmrSpanified = true;
  97. // turn off the throbber
  98. //$('#themer-toggle img.throbber').hide();
  99. }
  100. function thmrInPop(obj) {
  101. //is the element in either the popup box or the toggle div?
  102. if (obj.id == "themer-popup" || obj.id == "themer-toggle") return true;
  103. if (obj.parentNode) {
  104. while (obj = obj.parentNode) {
  105. if (obj.id=="themer-popup" || obj.id == "themer-toggle") return true;
  106. }
  107. }
  108. return false;
  109. }
  110. function themerEvent(e) {
  111. if (!e) {
  112. var e = window.event;
  113. };
  114. if (e.target) var tg = e.target;
  115. else if (e.srcElement) var tg = e.srcElement;
  116. return themerDoIt(tg);
  117. }
  118. /**
  119. * Find all parents with @thmr"
  120. */
  121. function thmrFindParents(obj) {
  122. var parents = new Array();
  123. if ($(obj).attr('thmr') != undefined) {
  124. parents[parents.length] = obj;
  125. }
  126. if (obj && obj.parentNode) {
  127. while ((obj = obj.parentNode) && (obj.nodeType != 9)) {
  128. if ($(obj).attr('thmr') != undefined) {
  129. parents[parents.length] = obj;
  130. }
  131. }
  132. }
  133. return parents;
  134. }
  135. /**
  136. * Check to see if object is a block element
  137. */
  138. function thmrIsBlock(obj) {
  139. if (obj.style.display == 'block') {
  140. return true;
  141. }
  142. else if (obj.style.display == 'inline' || obj.style.display == 'none') {
  143. return false;
  144. }
  145. if (obj.tagName != undefined) {
  146. var i = blocks.length;
  147. if (i > 0) {
  148. do {
  149. if (blocks[i] === obj.tagName) {
  150. return true;
  151. }
  152. } while (i--);
  153. }
  154. }
  155. return false;
  156. }
  157. function thmrRefreshCollapse() {
  158. $('#themer-popup .devel-obj-output dt').each(function() {
  159. $(this).toggle(function() {
  160. $(this).parent().children('dd').show();
  161. }, function() {
  162. $(this).parent().children('dd').hide();
  163. });
  164. });
  165. }
  166. /**
  167. * Rebuild the popup
  168. *
  169. * @param objs
  170. * The array of the current object and its parents. Current object is first element of the array
  171. */
  172. function thmrRebuildPopup(objs) {
  173. // rebuild the popup box
  174. var id = objs[0].getAttribute('thmr');
  175. // vars is the settings array element for this theme item
  176. var vars = Drupal.settings[id];
  177. // strs is the translatable strings
  178. var strs = Drupal.settings.thmrStrings;
  179. var type = vars.type;
  180. var key = vars.used;
  181. // clear out the initial "click on any element" starter text
  182. $('#themer-popup div.starter').empty();
  183. if (type == 'func') {
  184. // populate the function name
  185. $('#themer-popup dd.key').empty().prepend('<a href="'+ strs.api_site +'api/search/'+ strs.drupal_version +'/'+ key +'" title="'+ strs.drupal_api_docs +'">'+ key +'()</a>');
  186. $('#themer-popup dt.key-type').empty().prepend(strs.function_called);
  187. }
  188. else {
  189. // populate the template name
  190. $('#themer-popup dd.key').empty().prepend(key);
  191. $('#themer-popup dt.key-type').empty().prepend(strs.template_called);
  192. }
  193. // parents
  194. var parents = '';
  195. parents = strs.parents +' <span class="parents">';
  196. for(i=1;i<objs.length;i++) {
  197. var thmrid = $(objs[i]).attr('thmr')
  198. var pvars = Drupal.settings[thmrid];
  199. parents += i!=1 ? '&lt; ' : '';
  200. // populate the parents
  201. // each parent is wrapped with a span containing a 'trig' attribute with the id of the element it represents
  202. parents += '<span class="parent" trig="'+ thmrid +'">'+ pvars.name +'</span> ';
  203. }
  204. parents += '</span>';
  205. // stick the parents spans in the #parents div
  206. $('#themer-popup #parents').empty().prepend(parents);
  207. $('#themer-popup span.parent')
  208. .click(function() {
  209. var thmr_id = $(this).attr('trig');
  210. var thmr_obj = $('[thmr = "' + thmr_id + '"]')[0];
  211. themerDoIt(thmr_obj);
  212. })
  213. .hover(
  214. function() {
  215. // make them highlight their element on mouseover
  216. $('#'+ $(this).attr('trig')).trigger('mouseover');
  217. },
  218. function() {
  219. // and unhilight on mouseout
  220. $('#'+ $(this).attr('trig')).trigger('mouseout');
  221. }
  222. );
  223. if (vars == undefined) {
  224. // if there's no item in the settings array for this element
  225. $('#themer-popup dd.candidates').empty();
  226. $('#themer-popup dd.preprocessors').empty();
  227. $('#themer-popup div.attributes').empty();
  228. $('#themer-popup div.used').empty();
  229. $('#themer-popup div.duration').empty();
  230. }
  231. else {
  232. $('#themer-popup div.duration').empty().prepend('<span class="dt">' + strs.duration + '</span>' + vars.duration + ' ms');
  233. $('#themer-popup dd.candidates').empty().prepend(vars.candidates.join('<span class="delimiter"> < </span>'));
  234. $('#themer-popup dd.preprocessors').empty().prepend(vars.preprocessors.join('<span class="delimiter"> + </span>'));
  235. $('#themer-popup dt.preprocessors-type').empty().prepend(strs.preprocessors);
  236. $('#themer-popup dd.processors').empty().prepend(vars.processors.join('<span class="delimiter"> + </span>'));
  237. $('#themer-popup dt.processors-type').empty().prepend(strs.processors);
  238. var uri = Drupal.settings.devel_themer_uri + '/' + id;
  239. if (type == 'func') {
  240. // populate the candidates
  241. $('#themer-popup dt.candidates-type').empty().prepend(strs.candidate_functions);
  242. }
  243. else {
  244. $('#themer-popup dt.candidates-type').empty().prepend(strs.candidate_files);
  245. }
  246. // Use drupal ajax to do what we need
  247. vars_div_array = $('div.themer-variables');
  248. vars_div = vars_div_array[0];
  249. // Programatically using the drupal ajax things is tricky, so cheat.
  250. dummy_link = $('<a href="'+uri+'" class="use-ajax">Loading Vars</a>');
  251. $(vars_div).append(dummy_link);
  252. Drupal.attachBehaviors(vars_div);
  253. dummy_link.click();
  254. thmrRefreshCollapse();
  255. }
  256. // stop throbber
  257. //$('#themer-popup img.throbber').hide();
  258. }
  259. })(jQuery);