Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: chrome/content/composer.js

Issue 5201912261509120: issue #390 - remove already integrated parts From EHH (Closed)
Patch Set: Created July 18, 2014, 11:17 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/content/composer.xul » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * This Source Code is subject to the terms of the Mozilla Public License
3 * version 2.0 (the "License"). You can obtain a copy of the License at
4 * http://mozilla.org/MPL/2.0/.
5 */
6
7 let {Prefs} = require("prefs");
8
9 let domainData;
10 let nodeData;
11 let selectedNode = null;
12 let advancedMode = false;
13 let treeView = null;
14 let stylesheetData;
15 let previewStyle = null;
16 let doc;
17
18 let abpURL = Cc["@adblockplus.org/abp/public;1"].getService(Ci.nsIURI);
19 Cu.import(abpURL.spec);
20
21 /*******************
22 * NodeData object *
23 *******************/
24
25 function NodeData(node, parentNode) {
26 this.tagName = {value: node.tagName, checked: false};
27
28 if (typeof parentNode == "undefined")
29 parentNode = (node.parentNode && node.parentNode.nodeType == node.ELEMENT_NO DE ? new NodeData(node.parentNode) : null);
30 this.parentNode = parentNode;
31
32 var prevSibling = node.previousSibling;
33 while (prevSibling && prevSibling.nodeType != node.ELEMENT_NODE)
34 prevSibling = prevSibling.previousSibling;
35 this.prevSibling = (prevSibling ? new NodeData(prevSibling, this.parentNode) : null);
36
37 if (parentNode && !prevSibling)
38 this.firstChild = {checked: false};
39
40 var nextSibling = node.nextSibling;
41 while (nextSibling && nextSibling.nodeType != node.ELEMENT_NODE)
42 nextSibling = nextSibling.nextSibling;
43 if (parentNode && !nextSibling)
44 this.lastChild = {checked: false};
45
46 this.attributes = [];
47 for (var i = 0; i < node.attributes.length; i++) {
48 var attribute = node.attributes[i];
49 var data = {name: attribute.name, value: attribute.value, selected: attribut e.value, checked: false};
50 if (data.name == "id" || data.name == "class")
51 this.attributes.unshift(data);
52 else
53 this.attributes.push(data);
54 }
55
56 if (this.attributes.length >= 2 && this.attributes[1].name == "id") {
57 // Make sure ID attribute comes first
58 var tmp = this.attributes[1];
59 this.attributes[1] = this.attributes[0];
60 this.attributes[0] = tmp;
61 }
62
63 this.customCSS = {selected: "", checked: false};
64 }
65
66 /*******************
67 * TreeView object *
68 *******************/
69
70 function TreeView(tree) {
71 var origView = tree.view;
72 this.getRowProperties = TreeView_getRowProperties;
73 this.getCellProperties = TreeView_getCellProperties;
74
75 createQIProxy(this, origView);
76
77 for (var key in origView) {
78 if (this.hasOwnProperty(key))
79 continue;
80
81 createPropertyProxy(this, origView, key);
82 }
83
84 tree.view = this;
85 }
86
87 function createQIProxy(obj, orig) {
88 obj.QueryInterface = function(iid) {
89 var impl = orig.QueryInterface(iid);
90 if (impl != orig)
91 throw Cr.NS_ERROR_NO_INTERFACE;
92
93 return obj;
94 };
95 }
96
97 function createPropertyProxy(obj, orig, key) {
98 if (typeof orig[key] == "function") {
99 obj[key] = function() {
100 return orig[key].apply(orig, arguments);
101 };
102 }
103 else {
104 obj.__defineGetter__(key, function() {
105 return orig[key];
106 });
107 obj.__defineSetter__(key, function(value) {
108 orig[key] = value;
109 });
110 }
111 }
112
113 function TreeView_getRowProperties(row) {
114 let properties = "selected-" + this.selection.isSelected(row);
115
116 var item = this.getItemAtIndex(row);
117 if (item && (item.nodeData.expression != "*" || item.nodeData == nodeData))
118 properties += " anchor";
119
120 return properties;
121 }
122
123 function TreeView_getCellProperties(row, col) {
124 this.getRowProperties(row);
125 }
126
127 /*********************
128 * General functions *
129 *********************/
130
131 function init() {
132 var element = window.arguments[0];
133 doc = element.ownerDocument;
134 var wnd = doc.defaultView;
135
136 // Check whether element hiding group is disabled
137 let subscription = AdblockPlus.getSubscription("~eh~");
138 if (subscription && subscription.disabled)
139 {
140 let warning = document.getElementById("groupDisabledWarning");
141 if (/\?1\?/.test(warning.textContent))
142 warning.textContent = warning.textContent.replace(/\?1\?/g, subscription.t itle);
143 warning.hidden = false;
144 }
145
146 nodeData = new NodeData(element);
147 nodeData.tagName.checked = true;
148 if (nodeData.attributes.length > 0)
149 {
150 let maxLen = 0;
151 let bestAttr = null;
152 for (let i = 0; i < nodeData.attributes.length; i++)
153 {
154 let len = nodeData.attributes[i].value.length;
155 if ((nodeData.attributes[i].name == "id" || nodeData.attributes[i].name == "class") && len)
156 {
157 len = 0x7FFFFFFF;
158 nodeData.tagName.checked = false;
159 }
160 if (len > maxLen)
161 {
162 maxLen = len;
163 bestAttr = nodeData.attributes[i];
164 }
165 }
166 if (bestAttr)
167 {
168 bestAttr.selected = bestAttr.value;
169 bestAttr.checked = true;
170 }
171 }
172
173 let domain = wnd.location.hostname;
174 let selectedDomain;
175 switch (Prefs.composer_defaultDomain)
176 {
177 case 0:
178 selectedDomain = "";
179 break;
180 case 1:
181 try
182 {
183 // EffectiveTLDService will throw for IP addresses, just go to the next case then
184 let effectiveTLD = Cc["@mozilla.org/network/effective-tld-service;1"].ge tService(Ci.nsIEffectiveTLDService);
185 selectedDomain = effectiveTLD.getPublicSuffixFromHost(domain);
186 break;
187 } catch (e) {}
188 case 2:
189 try
190 {
191 // EffectiveTLDService will throw for IP addresses, just go to the next case then
192 let effectiveTLD = Cc["@mozilla.org/network/effective-tld-service;1"].ge tService(Ci.nsIEffectiveTLDService);
193 selectedDomain = effectiveTLD.getBaseDomainFromHost(domain);
194 break;
195 } catch (e) {}
196 case 3:
197 selectedDomain = domain.replace(/^www\./, "");
198 break;
199 default:
200 selectedDomain = domain;
201 break;
202 }
203 domainData = {value: domain, selected: selectedDomain};
204
205 fillDomains(domainData);
206 fillNodes(nodeData);
207 setAdvancedMode(document.documentElement.getAttribute("advancedMode") == "true ");
208 updateExpression();
209
210 setTimeout(function() {
211 document.getElementById("domainGroup").selectedItem.focus();
212 if (document.getElementById("preview").checked)
213 togglePreview(true);
214 }, 0);
215 }
216
217 function updateExpression()
218 {
219 var curNode = nodeData;
220
221 function escapeName(name)
222 {
223 return name.replace(/([^\w\-])/g, "\\$1")
224 .replace(/\\([\{\}])/g, escapeChar);
225 }
226
227 while (curNode)
228 {
229 let expression = (curNode.tagName.checked ? curNode.tagName.value : "");
230
231 for (var i = 0; i < curNode.attributes.length; i++)
232 {
233 var attr = curNode.attributes[i];
234
235 if (attr.checked) {
236 var escapedName = escapeName(attr.name);
237 if (attr.selected != "")
238 {
239 var op = "*=";
240 if (attr.selected == attr.value)
241 op = "=";
242 else if (attr.value.substr(0, attr.selected.length) == attr.selected)
243 op = "^=";
244 else if (attr.value.substr(attr.value.length - attr.selected.length) = = attr.selected)
245 op = "$=";
246
247 let useFallback = false;
248 if (attr.name == "id" && op == "=")
249 expression += "#" + escapeName(attr.selected).replace(/^([^a-zA-Z\\] )/, escapeChar).replace(/\\(\s)$/, escapeChar);
250 else if (attr.name == "class" && /\S/.test(attr.selected))
251 {
252 let knownClasses = {};
253 for each (let cls in attr.value.split(/\s+/))
254 knownClasses[cls] = true;
255
256 let classes = attr.selected.split(/\s+/).filter(function(cls) cls != "");
257 if (classes.every(function(cls) knownClasses.hasOwnProperty(cls)))
258 expression += "." + classes.map(escapeName).join(".");
259 else
260 useFallback = true;
261 }
262 else
263 useFallback = true;
264
265 if (useFallback)
266 {
267 var escapedValue = attr.selected.replace(/(["\\])/g, '\\$1')
268 .replace(/([\{\}])/g, escapeChar)
269 .replace(/([^\S ])/g, escapeChar);
270 expression += "[" + escapedName + op + '"' + escapedValue + '"' + "] ";
271 }
272 }
273 else
274 {
275 expression += "[" + escapedName + "]";
276 }
277 }
278 }
279
280 if (curNode.customCSS.checked && curNode.customCSS.selected != "")
281 {
282 expression += curNode.customCSS.selected
283 .replace(/([\{\}])/g, escapeChar)
284 .replace(/([^\S ])/g, escapeChar);
285 }
286
287 if ("firstChild" in curNode && curNode.firstChild.checked)
288 expression += ":first-child";
289 if ("lastChild" in curNode && curNode.lastChild.checked)
290 expression += ":last-child";
291
292 if (expression == "")
293 expression = "*";
294
295 curNode.expression = expression;
296
297 if (curNode.prevSibling)
298 curNode = curNode.prevSibling;
299 else
300 curNode = curNode.parentNode;
301 }
302
303 let expression = nodeData.expression;
304
305 var isParent = false;
306 var isRemoteParent = false;
307 var siblingCount = 0;
308 var firstRun = true;
309
310 var curData = nodeData;
311 while (curData) {
312 if (!firstRun && curData.expression != "*") {
313 var parentRelation = "";
314 if (isRemoteParent)
315 parentRelation = " ";
316 else if (isParent)
317 parentRelation = " > ";
318
319 var siblingRelation = "";
320 for (var i = 0; i < siblingCount; i++)
321 siblingRelation += "* + ";
322 siblingRelation = siblingRelation.replace(/^\*/, '');
323
324 var relation;
325 if (parentRelation != "" && siblingRelation != "")
326 relation = siblingRelation + "*" + parentRelation;
327 else if (parentRelation != "")
328 relation = parentRelation;
329 else
330 relation = siblingRelation;
331
332 expression = curData.expression + relation + expression;
333
334 isParent = false;
335 isRemoteParent = false;
336 siblingCount = 0;
337 }
338 firstRun = false;
339
340 if (curData.prevSibling) {
341 siblingCount++;
342 curData = curData.prevSibling;
343 }
344 else if (curData.parentNode) {
345 siblingCount = 0;
346 if (isParent)
347 isRemoteParent = true;
348 else
349 isParent = true;
350 curData = curData.parentNode;
351 }
352 else
353 curData = null;
354 }
355
356 stylesheetData = expression + "{display: none !important;}";
357 expression = domainData.selected + "##" + expression;
358
359 document.getElementById("expression").value = expression;
360
361 var tree = document.getElementById("nodes-tree");
362 if (tree.view && tree.view.selection)
363 tree.treeBoxObject.invalidateRow(tree.view.selection.currentIndex);
364
365 if (previewStyle)
366 previewStyle.textContent = stylesheetData;
367 }
368
369 function escapeChar(dummy, match)
370 {
371 return "\\" + match.charCodeAt(0).toString(16) + " ";
372 }
373
374 function fillDomains(domainData) {
375 var list = document.getElementById("domainGroup");
376
377 var commandHandler = function() {
378 changeDomain(this);
379 };
380
381 var node = document.createElement("radio");
382 node.setAttribute("label", list.getAttribute("_labelnone"));
383 node.setAttribute("value", "");
384 node.addEventListener("command", commandHandler, false);
385 if (domainData.selected == "")
386 node.setAttribute("selected", "true");
387 list.appendChild(node);
388
389 var parts = domainData.value.split(".");
390 if (parts[0] == "")
391 parts.shift();
392
393 for (var i = 1; i <= parts.length; i++) {
394 if (parts[parts.length - i] == "")
395 continue;
396
397 var curDomain = parts.slice(parts.length - i).join(".");
398
399 node = document.createElement("radio");
400 node.setAttribute("label", curDomain)
401 node.setAttribute("value", curDomain);
402 node.addEventListener("command", commandHandler, false);
403 if (domainData.selected == curDomain)
404 node.setAttribute("selected", "true");
405 list.appendChild(node);
406 }
407 }
408
409 function fillNodes(nodeData) {
410 var curContainer = document.createElement("treechildren");
411 var curChildren = null;
412 while (nodeData) {
413 var id = "";
414 var className = "";
415 var i = 0;
416 if (nodeData.attributes.length > i && nodeData.attributes[i].name == "id")
417 id = nodeData.attributes[i++].value;
418 if (nodeData.attributes.length > i && nodeData.attributes[i].name == "class" )
419 className = nodeData.attributes[i++].value;
420
421 var item = document.createElement("treeitem");
422 var row = document.createElement("treerow");
423
424 var cell = document.createElement("treecell");
425 cell.setAttribute("label", nodeData.tagName.value);
426 row.appendChild(cell);
427
428 cell = document.createElement("treecell");
429 cell.setAttribute("label", id);
430 row.appendChild(cell);
431
432 cell = document.createElement("treecell");
433 cell.setAttribute("label", className);
434 row.appendChild(cell);
435
436 item.appendChild(row);
437 item.nodeData = nodeData;
438
439 if (curChildren) {
440 item.appendChild(curChildren);
441 item.setAttribute("container", "true");
442 item.setAttribute("open", "true");
443 }
444 curChildren = null;
445
446 if (curContainer.firstChild)
447 curContainer.insertBefore(item, curContainer.firstChild);
448 else
449 curContainer.appendChild(item);
450
451 if (nodeData.prevSibling)
452 nodeData = nodeData.prevSibling;
453 else if (nodeData.parentNode) {
454 curChildren = curContainer;
455 curContainer = document.createElement("treechildren");
456 nodeData = nodeData.parentNode;
457 }
458 else
459 nodeData = null;
460 }
461
462 var tree = document.getElementById("nodes-tree");
463 var body = document.getElementById("nodes-tree-children");
464 while (curContainer.firstChild)
465 body.appendChild(curContainer.firstChild);
466 }
467
468 function createAttribute(template, attr, text, value)
469 {
470 template = E(template == "basic" ? "basicAttributeTemplate" : "advancedAttribu teTemplate");
471
472 let result = template.cloneNode(true);
473 result.removeAttribute("id");
474 result.removeAttribute("hidden");
475 result.attr = attr;
476
477 let checkbox = result.getElementsByClassName("checkbox")[0];
478 checkbox.setAttribute("checked", attr.checked);
479 checkbox.attr = attr;
480
481 let label = result.getElementsByClassName("label");
482 if (label.length)
483 {
484 label = label[0];
485 label.setAttribute("value", text);
486
487 let randID = "i" + String(Math.random()).replace(/\D/g, "");
488 checkbox.setAttribute("id", randID);
489 label.setAttribute("control", randID);
490 }
491 else
492 checkbox.setAttribute("label", text);
493
494 let textbox = result.getElementsByClassName("textbox");
495 if (textbox.length)
496 {
497 textbox = textbox[0];
498 textbox.setAttribute("value", value);
499 textbox.attr = attr;
500 }
501
502 return result;
503 }
504
505 function fillAttributes(nodeData)
506 {
507 selectedNode = nodeData;
508
509 let list = document.getElementById("attributes-list");
510 while(list.firstChild)
511 list.removeChild(list.firstChild);
512
513 // Add tag name entry
514 let node = createAttribute("basic", nodeData.tagName, list.getAttribute("_labe ltagname") + " " + nodeData.tagName.value);
515 list.appendChild(node);
516
517 // Add first/last child entries
518 if (advancedMode && "firstChild" in nodeData)
519 {
520 node = createAttribute("basic", nodeData.firstChild, list.getAttribute("_lab elfirstchild"));
521 list.appendChild(node);
522 }
523 if (advancedMode && "lastChild" in nodeData)
524 {
525 node = createAttribute("basic", nodeData.lastChild, list.getAttribute("_labe llastchild"));
526 list.appendChild(node);
527 }
528
529 // Add attribute entries
530 for (let i = 0; i < nodeData.attributes.length; i++)
531 {
532 let attr = nodeData.attributes[i];
533 node = createAttribute(advancedMode ? "advanced" : "basic", attr, attr.name + ": " + attr.value, attr.selected);
534 list.appendChild(node);
535 }
536
537 if (advancedMode)
538 {
539 // Add custom CSS entry
540 node = createAttribute("advanced", nodeData.customCSS, list.getAttribute("_l abelcustom"), nodeData.customCSS.selected);
541 list.appendChild(node);
542 }
543 }
544
545 function togglePreview(preview) {
546 if (preview) {
547 if (!previewStyle || !previewStyle.parentNode) {
548 previewStyle = doc.createElementNS("http://www.w3.org/1999/xhtml", "style" );
549 previewStyle.setAttribute("type", "text/css");
550 doc.documentElement.appendChild(previewStyle);
551 }
552 previewStyle.textContent = stylesheetData;
553 }
554 else {
555 try
556 {
557 if (previewStyle && previewStyle.parentNode)
558 previewStyle.parentNode.removeChild(previewStyle);
559 }
560 catch (e)
561 {
562 // if the window was closed (reloaded) we end up with dead object referenc e
563 // https://bugzilla.mozilla.org/show_bug.cgi?id=695480
564 // just ignore this case
565 }
566 previewStyle = null;
567 }
568 }
569
570 function changeDomain(node) {
571 domainData.selected = node.getAttribute("value");
572 updateExpression();
573 }
574
575 function toggleAttr(node) {
576 node.attr.checked = node.checked;
577 updateExpression();
578 }
579
580 function setSelectedAttrValue(node) {
581 node.attr.selected = node.value;
582 if (node.attr.checked)
583 updateExpression();
584 }
585
586 function setAdvancedMode(mode) {
587 advancedMode = mode;
588
589 var dialog = document.documentElement;
590 dialog.setAttribute("advancedMode", advancedMode);
591
592 var button = dialog.getButton("disclosure");
593 button.setAttribute("label", dialog.getAttribute(advancedMode ? "buttonlabeldi sclosure_off" : "buttonlabeldisclosure_on"));
594
595 fillAttributes(nodeData);
596
597 if (advancedMode) {
598 setTimeout(function() {
599 var tree = document.getElementById("nodes-tree");
600
601 if (!treeView)
602 treeView = new TreeView(tree);
603
604 if (selectedNode) {
605 // Expand all containers
606 var items = tree.getElementsByTagName("treeitem");
607 for (var i = 0; i < items.length; i++)
608 if (items[i].getAttribute("container") == "true")
609 items[i].setAttribute("open", "true");
610
611 tree.treeBoxObject.ensureRowIsVisible(tree.view.rowCount - 1);
612 tree.view.selection.select(tree.view.rowCount - 1);
613 }
614 }, 0);
615 }
616 }
617
618 function updateNodeSelection() {
619 var tree = document.getElementById("nodes-tree");
620 var selection = tree.view.selection;
621 if (selection.count < 1)
622 return;
623
624 var min = {};
625 selection.getRangeAt(0, min, {});
626
627 var item = tree.view
628 .QueryInterface(Ci.nsITreeContentView)
629 .getItemAtIndex(min.value);
630 if (!item || !item.nodeData)
631 return;
632
633 fillAttributes(item.nodeData);
634 }
635
636 function addExpression()
637 {
638 AdblockPlus.addPatterns([document.getElementById("expression").value]);
639
640 togglePreview(false);
641 }
OLDNEW
« no previous file with comments | « no previous file | chrome/content/composer.xul » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld