Package cssutils :: Package stylesheets :: Module medialist |
[hide private]
[frames] | no frames]

# Source Code for Module cssutils.stylesheets.medialist

      1  """
      2  MediaList implements DOM Level 2 Style Sheets MediaList.
      3
      4  TODO:
      5      - delete: maybe if deleting from all, replace *all* with all others?
      6      - is unknown media an exception?
      7  """
      8  __all__ = ['MediaList']
      9  __docformat__ = 'restructuredtext'
     10  __author__ = '$LastChangedBy: cthedot $'
     11  __date__ = '$LastChangedDate: 2008-02-12 23:43:05 +0100 (Di, 12 Feb 2008) $'
     12  __version__ = '$LastChangedRevision: 1049 $'
     13
     14  import xml.dom
     15  import cssutils
     16  from cssutils.css import csscomment
     17  from mediaquery import MediaQuery
     18
     19 -class MediaList(cssutils.util.Base, cssutils.util.ListSeq):
     20      """
     21      Provides the abstraction of an ordered collection of media,
     22      without defining or constraining how this collection is
     23      implemented.
     24
     25      A media is always an instance of MediaQuery.
     26
     27      An empty list is the same as a list that contains the medium "all".
     28
     29      Properties
     30      ==========
     31      length:
     32          The number of MediaQuery objects in the list.
     33      mediaText: of type DOMString
     34          The parsable textual representation of this MediaList
     35      self: a list (cssutils)
     36          All MediaQueries in this MediaList
     37      wellformed:
     38          if this list is wellformed
     39
     40      Format
     41      ======
     42      ::
     43
     44          medium [ COMMA S* medium ]*
     45
     46      New::
     47
     48          <media_query> [, <media_query> ]*
     49      """
     50 -    def __init__(self, mediaText=None, readonly=False):
     51          """
     52          mediaText
     53              unicodestring of parsable comma separared media
     54              or a list of media
     55          """
     56          super(MediaList, self).__init__()
     57
     58          if isinstance(mediaText, list):
     59              mediaText = u','.join(mediaText)
     60
     61          if mediaText:
     62              self.mediaText = mediaText
     63
     64          self._readonly = readonly
     65
     66      length = property(lambda self: len(self),
     67          doc="(DOM readonly) The number of media in the list.")
     68
     69 -    def _getMediaText(self):
     70          """
     71          returns serialized property mediaText
     72          """
     73          return cssutils.ser.do_stylesheets_medialist(self)
     74
     75 -    def _setMediaText(self, mediaText):
     76          """
     77          mediaText
     78              simple value or comma-separated list of media
     79
     80          DOMException
     81
     82          - SYNTAX_ERR: (MediaQuery)
     83            Raised if the specified string value has a syntax error and is
     84            unparsable.
     85          - NO_MODIFICATION_ALLOWED_ERR: (self)
     86            Raised if this media list is readonly.
     87          """
     88          self._checkReadonly()
     89          wellformed = True
     90          tokenizer = self._tokenize2(mediaText)
     91          newseq = []
     92
     93          expected = None
     94          while True:
     95              # find all upto and including next ",", EOF or nothing
     96              mqtokens = self._tokensupto2(tokenizer, listseponly=True)
     97              if mqtokens:
     98                  if self._tokenvalue(mqtokens[-1]) == ',':
     99                      expected = mqtokens.pop()
    100                  else:
    101                      expected = None
    102
    103                  mq = MediaQuery(mqtokens)
    104                  if mq.wellformed:
    105                      newseq.append(mq)
    106                  else:
    107                      wellformed = False
    108                      self._log.error(u'MediaList: Invalid MediaQuery: %s' %
    109                                      self._valuestr(mqtokens))
    110              else:
    111                  break
    112
    113          # post condition
    114          if expected:
    115              wellformed = False
    116              self._log.error(u'MediaList: Cannot end with ",".')
    117
    118          if wellformed:
    119              del self[:]
    120              for mq in newseq:
    121                  self.appendMedium(mq)
    122
    123      mediaText = property(_getMediaText, _setMediaText,
    124          doc="""(DOM) The parsable textual representation of the media list.
    125              This is a comma-separated list of media.""")
    126
    127      wellformed = property(lambda self: True)
    128
    129 -    def __prepareset(self, newMedium):
    130          # used by appendSelector and __setitem__
    131          self._checkReadonly()
    132
    133          if not isinstance(newMedium, MediaQuery):
    134              newMedium = MediaQuery(newMedium)
    135
    136          if newMedium.wellformed:
    137              return newMedium
    138
    139 -    def __setitem__(self, index, newMedium):
    140          """
    141          overwrites ListSeq.__setitem__
    142
    143          Any duplicate items are **not** removed.
    144          """
    145          newMedium = self.__prepareset(newMedium)
    146          if newMedium:
    147              self.seq[index] = newMedium
    148          # TODO: remove duplicates?
    149
    150 -    def appendMedium(self, newMedium):
    151          """
    152          (DOM)
    153          Adds the medium newMedium to the end of the list. If the newMedium
    154          is already used, it is first removed.
    155
    156          newMedium
    157              a string or a MediaQuery object
    158
    159          returns if newMedium is wellformed
    160
    161          DOMException
    162
    163          - INVALID_CHARACTER_ERR: (self)
    164            If the medium contains characters that are invalid in the
    165            underlying style language.
    166          - NO_MODIFICATION_ALLOWED_ERR: (self)
    167            Raised if this list is readonly.
    168          """
    169          newMedium = self.__prepareset(newMedium)
    170
    171          if newMedium:
    172              mts = [self._normalize(mq.mediaType) for mq in self]
    173              newmt = self._normalize(newMedium.mediaType)
    174
    175              if newmt in mts:
    176                  self.deleteMedium(newmt)
    177                  self.seq.append(newMedium)
    178              elif u'all' == newmt:
    179                  # remove all except handheld (Opera)
    180                  h = None
    181                  for mq in self:
    182                      if mq.mediaType == u'handheld':
    183                          h = mq
    184                  del self[:]
    185                  self.seq.append(newMedium)
    186                  if h:
    187                      self.append(h)
    188              elif u'all' in mts:
    189                  if u'handheld' == newmt:
    190                      self.seq.append(newMedium)
    191              else:
    192                  self.seq.append(newMedium)
    193
    194              return True
    195
    196          else:
    197              return False
    198
    199 -    def append(self, newMedium):
    200          "overwrites ListSeq.append"
    201          self.appendMedium(newMedium)
    202
    203 -    def deleteMedium(self, oldMedium):
    204          """
    205          (DOM)
    206          Deletes the medium indicated by oldMedium from the list.
    207
    208          DOMException
    209
    210          - NO_MODIFICATION_ALLOWED_ERR: (self)
    211            Raised if this list is readonly.
    212          - NOT_FOUND_ERR: (self)
    213            Raised if oldMedium is not in the list.
    214          """
    215          self._checkReadonly()
    216          oldMedium = self._normalize(oldMedium)
    217
    218          for i, mq in enumerate(self):
    219              if self._normalize(mq.mediaType) == oldMedium:
    220                  del self[i]
    221                  break
    222          else:
    223              raise xml.dom.NotFoundErr(
    224                  u'"%s" not in this MediaList' % oldMedium)
    225
    226 -    def item(self, index):
    227          """
    228          (DOM)
    229          Returns the mediaType of the index'th element in the list.
    230          If index is greater than or equal to the number of media in the
    231          list, returns None.
    232          """
    233          try:
    234              return self[index].mediaType
    235          except IndexError:
    236              return None
    237
    238 -    def __repr__(self):
    239          return "cssutils.stylesheets.%s(mediaText=%r)" % (
    240                  self.__class__.__name__, self.mediaText)
    241
    242 -    def __str__(self):
    243          return "<cssutils.stylesheets.%s object mediaText=%r at 0x%x>" % (
    244                  self.__class__.__name__, self.mediaText, id(self))
    245