<filename>django_cradmin/javascriptregistry/component.py
# -*- coding: utf-8 -*-
import re

from django.templatetags.static import static as django_static


COMPONENT_ID_REGEX = re.compile(r'^[a-z][a-z0-9_]*[a-z0-9]$')


class ComponentIdFormatError(Exception):
    """
    Raised by :class:`.AbstractJsComponent` if the component_id is
    not formatted according to the rules.
    """


class AbstractJsComponent(object):
    """
    Base class for all javascript components.

    .. attribute:: component_id

        Set to :meth:`.get_component_id` in __init__ if the component ID passes
        the validation checks.
    """
    @classmethod
    def get_component_id(cls):
        """
        Get a unique ID for this javascript component.

        Can only contain a-z, 0-9 and ``_``. The first letter can only be a-z,
        and the last letter can not be ``_``.

        Must be overridden in subclasses.
        """
        raise NotImplementedError()

    def __init__(self, request):
        self.request = request
        self.component_id = self.get_component_id()
        if not COMPONENT_ID_REGEX.match(self.component_id):
            raise ComponentIdFormatError(
                'Invalid component_id: {}. Must start with a-z, end with a-z or 0-9, and'
                'the letters between the start and end can only be a-z, 0-9 and _. Must '
                'be at least 2 letters.'.format(
                    self.component_id))

    def get_dependencies(self):
        """
        Get a list of :meth:`component ids <.get_component_id>` that this javascript
        component depends on.
        """
        return []

    def get_static_url(self, path):
        """
        Works just like the ``static`` template tag.

        Args:
            path (str): The path relative to the static directory.

        Returns:
            str: The static URL.

        """
        return django_static(path)

    def get_sourceurls(self):
        """
        Get a list of javascript source files to load for this component.

        These URLs are added using ``<script>`` tags at the end of ``<body>``
        by the base cradmin templates.

        .. note:: If other components load the same source files, the template tags
            in the ``cradmin_javascriptregistry_tags`` template tag library
            ensures that one unique sources are loaded.
        """
        return []

    def get_head_sourceurls(self):
        """
        Just like :meth:`.get_sourceurls`, but added in the ``<head>`` tag.

        You should normally avoid using this because adding scripts to the
        head tag blocks page loading.
        """
        return []

    def get_javascript_code_after_sourceurls(self):
        """
        Javascript code to add inline in the body of the HTML page
        after loading the source URLs (see :meth:`.get_sourceurls`).

        See :meth:`.get_javascript_code_before_sourceurls` for more details.
        """
        return None

    def get_javascript_code_before_sourceurls(self):
        """
        Javascript code to add inline in the body of the HTML page
        before loading the source URLs (see :meth:`.get_sourceurls`).

        Should return javascript code as a string (no HTML tags).
        """
        return None

    def __eq__(self, other):
        """
        Javascript components are considered equal if their :attr:`~.AbstractJsComponent.component_id` match.
        """
        return other.component_id == self.component_id

<filename>django_cradmin/javascriptregistry/component.py
# -*- coding: utf-8 -*-
import re

from django.templatetags.static import static as django_static


COMPONENT_ID_REGEX = re.compile(r'^[a-z][a-z0-9_]*[a-z0-9]$')


class ComponentIdFormatError(Exception):
    """
    Raised by :class:`.AbstractJsComponent` if the component_id is
    not formatted according to the rules.
    """


class AbstractJsComponent(object):
    """
    Base class for all javascript components.

    .. attribute:: component_id

        Set to :meth:`.get_component_id` in __init__ if the component ID passes
        the validation checks.
    """
    @classmethod
    def get_component_id(cls):
        """
        Get a unique ID for this javascript component.

        Can only contain a-z, 0-9 and ``_``. The first letter can only be a-z,
        and the last letter can not be ``_``.

        Must be overridden in subclasses.
        """
        raise NotImplementedError()

    def __init__(self, request):
        self.request = request
        self.component_id = self.get_component_id()
        if not COMPONENT_ID_REGEX.match(self.component_id):
            raise ComponentIdFormatError(
                'Invalid component_id: {}. Must start with a-z, end with a-z or 0-9, and'
                'the letters between the start and end can only be a-z, 0-9 and _. Must '
                'be at least 2 letters.'.format(
                    self.component_id))

    def get_dependencies(self):
        """
        Get a list of :meth:`component ids <.get_component_id>` that this javascript
        component depends on.
        """
        return []

    def get_static_url(self, path):
        """
        Works just like the ``static`` template tag.

        Args:
            path (str): The path relative to the static directory.

        Returns:
            str: The static URL.

        """
        return django_static(path)

    def get_sourceurls(self):
        """
        Get a list of javascript source files to load for this component.

        These URLs are added using ``<script>`` tags at the end of ``<body>``
        by the base cradmin templates.

        .. note:: If other components load the same source files, the template tags
            in the ``cradmin_javascriptregistry_tags`` template tag library
            ensures that one unique sources are loaded.
        """
        return []

    def get_head_sourceurls(self):
        """
        Just like :meth:`.get_sourceurls`, but added in the ``<head>`` tag.

        You should normally avoid using this because adding scripts to the
        head tag blocks page loading.
        """
        return []

    def get_javascript_code_after_sourceurls(self):
        """
        Javascript code to add inline in the body of the HTML page
        after loading the source URLs (see :meth:`.get_sourceurls`).

        See :meth:`.get_javascript_code_before_sourceurls` for more details.
        """
        return None

    def get_javascript_code_before_sourceurls(self):
        """
        Javascript code to add inline in the body of the HTML page
        before loading the source URLs (see :meth:`.get_sourceurls`).

        Should return javascript code as a string (no HTML tags).
        """
        return None

    def __eq__(self, other):
        """
        Javascript components are considered equal if their :attr:`~.AbstractJsComponent.component_id` match.
        """
        return other.component_id == self.component_id

# -*- coding: utf-8 -*- Raised by :class:`.AbstractJsComponent` if the component_id is     not formatted according to the rules. Base class for all javascript components.      .. attribute:: component_id          Set to :meth:`.get_component_id` in __init__ if the component ID passes         the validation checks. Get a unique ID for this javascript component.          Can only contain a-z, 0-9 and ``_``. The first letter can only be a-z,         and the last letter can not be ``_``.          Must be overridden in subclasses. Get a list of :meth:`component ids <.get_component_id>` that this javascript         component depends on. Works just like the ``static`` template tag.          Args:             path (str): The path relative to the static directory.          Returns:             str: The static URL. Get a list of javascript source files to load for this component.          These URLs are added using ``<script>`` tags at the end of ``<body>``         by the base cradmin templates.          .. note:: If other components load the same source files, the template tags             in the ``cradmin_javascriptregistry_tags`` template tag library             ensures that one unique sources are loaded. Just like :meth:`.get_sourceurls`, but added in the ``<head>`` tag.          You should normally avoid using this because adding scripts to the         head tag blocks page loading. Javascript code to add inline in the body of the HTML page         after loading the source URLs (see :meth:`.get_sourceurls`).          See :meth:`.get_javascript_code_before_sourceurls` for more details. Javascript code to add inline in the body of the HTML page         before loading the source URLs (see :meth:`.get_sourceurls`).          Should return javascript code as a string (no HTML tags). Javascript components are considered equal if their :attr:`~.AbstractJsComponent.component_id` match.