8000 add ensureSingle & ensureSingleById lib methods · plotly/plotly.js@5cc9af9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5cc9af9

Browse files
committed
add ensureSingle & ensureSingleById lib methods
- meant to replace all our `selectAll().data([0])` calls by something DRYer and faster.
1 parent 7d881f6 commit 5cc9af9

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

src/lib/index.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,63 @@ lib.isD3Selection = function(obj) {
632632
return obj && (typeof obj.classed === 'function');
633633
};
634634

635+
/**
636+
* Append element to DOM only if not present.
637+
*
638+
* @param {d3 selection} parent : parent selection of the element in question
639+
* @param {string} nodeType : node type of element to append
640+
* @param {string} className : class name of element in question
641+
* @param {fn} enterFn (optional) : optional fn applied to entering elements only
642+
* @return {d3 selection} selection of new layer
643+
*
644+
* Previously, we were using the following pattern:
645+
*
646+
* ```
647+
* var sel = parent.selectAll('.' + className)
648+
* .data([0]);
649+
*
650+
* sel.enter().append(nodeType)
651+
* .classed(className, true);
652+
*
653+
* return sel;
654+
* ```
655+
*
656+
* in numerous places in our codebase to achieve the same behavior.
657+
*
658+
* The logic below performs much better, mostly as we are using
659+
* `.select` instead `.selectAll` that is `querySelector` instead of
660+
* `querySelectorAll`.
661+
*
662+
*/
663+
lib.ensureSingle = function(parent, nodeType, className, enterFn) {
664+
var sel = parent.select(nodeType + (className ? '.' + className : ''));
665+
if(sel.size()) return sel;
666+
667+
var layer = parent.append(nodeType).classed(className, true);
668+
if(enterFn) layer.call(enterFn);
669+
670+
return layer;
671+
};
672+
673+
/**
674+
* Same as Lib.ensureSingle, but using id as selector.
675+
* This version is mostly used for clipPath nodes.
676+
*
677+
* @param {d3 selection} parent : parent selection of the element in question
678+
* @param {string} nodeType : node type of element to append
679+
* @param {string} id : id of element in question
680+
* @param {fn} enterFn (optional) : optional fn applied to entering elements only
681+
* @return {d3 selection} selection of new layer
682+
*/
683+
lib.ensureSingleById = function(parent, nodeType, id, enterFn) {
684+
var sel = parent.select(nodeType + '#' + id);
685+
if(sel.size()) return sel;
686+
687+
var layer = parent.append(nodeType).attr('id', id);
688+
if(enterFn) layer.call(enterFn);
689+
690+
return layer;
691+
};
635692

636693
/**
637694
* Converts a string path to an object.

0 commit comments

Comments
 (0)
0