0

I want to handle helper functions (.closest() and others) with angularjs but I don't know how to do that.

My goal:

let el = e => angular.element(e);

el('#selector').helperFunction();
el('.selector').closest('.parent');

Small example with jquery:

jQuery.fn.extend({
  helperFunction: function() {
      // do stuff...
  }
});

$('#selector').helperFunction();

How can I achieve that with angularjs?

Tân
  • 1
  • 15
  • 56
  • 102
  • Not hard to search for this...lots of similar questions here http://stackoverflow.com/questions/7332179/how-to-recursively-search-all-parentnodes , http://stackoverflow.com/questions/25597321/what-is-the-javascript-equivalent-to-jquery-closest, http://stackoverflow.com/questions/18663941/finding-closest-element-without-jquery – charlietfl Jan 02 '17 at 08:40
  • Are you asking how to recreate closest() or how to extend angular.element (jQlite)? – charlietfl Jan 02 '17 at 08:43
  • @charlietfl Ya. `angular.element('#selector').closest('.parent')` instead of creating `closest` function. – Tân Jan 02 '17 at 08:44
  • @charlietfl One of answers you give me is like: `var closest = function (selector) { /*...*/ }`. It doesn't require `angular.element` – Tân Jan 02 '17 at 08:46
  • @charlietfl I've tried to search with another keywords and got 0 result before. I will try again with your advice and delete this question later. Thank you! – Tân Jan 02 '17 at 08:55
  • don't delete it. Is it enough to know to use angular.element.prototype? – charlietfl Jan 02 '17 at 08:56
  • @charlietfl I've found a way to do that but I'm not sure it's right or not. `angular.element.prototype.closest = function (selector) { /*...*/ }`. Then, `angular.element('#selector').closest('.parent')` – Tân Jan 02 '17 at 09:04
  • it works doesn't it? Keep in mind that angular.element was written to be a lot lighter than jQuery but be able to be jQuery when jQuery.js is included in page – charlietfl Jan 02 '17 at 09:05
  • @charlietfl Yes. It's working. Many thanks! – Tân Jan 02 '17 at 09:10
  • go ahead and answer your own question, will likely help someone down the road – charlietfl Jan 02 '17 at 09:12
  • @charlietfl Sorry for long time. I've just edited something to make it different from another answers. – Tân Jan 02 '17 at 09:55

1 Answers1

1

Here is a way to do that:

let el = e => angular.element(e);

angular.element.prototype.closest = function (selector) {
    if (typeof selector === 'string' && (/^(#|\.).+$/.test(selector) || (/^(a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdi|bdo|big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|datalist|dd|del|details|dfn|dialog|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|main|map|mark|menu|menuitem|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|track|tt|u|ul|var|video|wbr)$/.test(selector)))) {
        if (selector.startsWith('#')) {
            // finding via id

            let id = selector.substring(1, selector.length), parent = el(this).parent();

            while (parent.length) {
                if (parent.prop('id') === id) return parent;
                parent = parent.parent()
            }       
        } else if (selector.startsWith('.')) {
            // finding via class name

            let class_name = selector.substring(1, selector.length), parent = el(this).parent();

            while (parent.length) {
                if (parent.hasClass(class_name)) return parent;
                parent = parent.parent()
            }   
        } else {
            // finding via tag name

            let parent = el(this).parent();

            while (parent.length) {
                if (parent.prop('tagName') && parent.prop('tagName').toLowerCase() === selector.toLowerCase()) return parent;
                parent = parent.parent()
            }
        }
    }    
    return undefined
};

Then:

el('#selector').closest('#parent').css('color', '#f00');
el('#selector').closest('.parent').css('color', '#f00');
el('#selector').closest('div').css('color', '#f00');
Tân
  • 1
  • 15
  • 56
  • 102