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: 2007-11-25 18:03:51 +0100 (So, 25 Nov 2007) $'
     12  __version__ = '$LastChangedRevision: 692 $'
     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      valid:
     38          if this list is valid
     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          self.valid = True
     58
     59          if isinstance(mediaText, list):
     60              mediaText = u','.join(mediaText)
     61
     62          if mediaText:
     63              self.mediaText = mediaText
     64
     65          self._readonly = readonly
     66
     67 -    def _getLength(self):
     68          """
     69          returns count of media in this list which is not the same as
     70          len(MediaListInstance) which also contains CSSComments
     71          """
     72          return len(self)
     73
     74      length = property(_getLength,
     75          doc="(DOM readonly) The number of media in the list.")
     76
     77 -    def _getMediaText(self):
     78          """
     79          returns serialized property mediaText
     80          """
     81          return cssutils.ser.do_stylesheets_medialist(self)
     82
     83 -    def _setMediaText(self, mediaText):
     84          """
     85          mediaText
     86              simple value or comma-separated list of media
     87
     88          DOMException
     89
     90          - SYNTAX_ERR: (MediaQuery)
     91            Raised if the specified string value has a syntax error and is
     92            unparsable.
     93          - NO_MODIFICATION_ALLOWED_ERR: (self)
     94            Raised if this media list is readonly.
     95          """
     96          self._checkReadonly()
     97          valid = True
     98          tokenizer = self._tokenize2(mediaText)
     99          newseq = []
    100
    101          expected = None
    102          while True:
    103              # find all upto and including next ",", EOF or nothing
    104              mqtokens = self._tokensupto2(tokenizer, listseponly=True)
    105              if mqtokens:
    106                  if self._tokenvalue(mqtokens[-1]) == ',':
    107                      expected = mqtokens.pop()
    108                  else:
    109                      expected = None
    110
    111                  mq = MediaQuery(mqtokens)
    112                  if mq.valid:
    113                      newseq.append(mq)
    114                  else:
    115                      valid = False
    116                      self._log.error(u'MediaList: Invalid MediaQuery: %s' %
    117                                      self._valuestr(mqtokens))
    118              else:
    119                  break
    120
    121          # post condition
    122          if expected:
    123              valid = False
    124              self._log.error(u'MediaList: Cannot end with ",".')
    125
    126          if valid:
    127              del self[:]
    128              for mq in newseq:
    129                  self.appendMedium(mq)
    130
    131      mediaText = property(_getMediaText, _setMediaText,
    132          doc="""(DOM) The parsable textual representation of the media list.
    133              This is a comma-separated list of media.""")
    134
    135 -    def __prepareset(self, newMedium):
    136          # used by appendSelector and __setitem__
    137          self._checkReadonly()
    138
    139          if not isinstance(newMedium, MediaQuery):
    140              newMedium = MediaQuery(newMedium)
    141
    142          if newMedium.valid:
    143              return newMedium
    144
    145 -    def __setitem__(self, index, newMedium):
    146          """
    147          overwrites ListSeq.__setitem__
    148
    149          Any duplicate items are **not** removed.
    150          """
    151          newMedium = self.__prepareset(newMedium)
    152          if newMedium:
    153              self.seq[index] = newMedium
    154          # TODO: remove duplicates?
    155
    156 -    def appendMedium(self, newMedium):
    157          """
    158          (DOM)
    159          Adds the medium newMedium to the end of the list. If the newMedium
    160          is already used, it is first removed.
    161
    162          newMedium
    163              a string or a MediaQuery object
    164
    165          returns if newMedium is valid
    166
    167          DOMException
    168
    169          - INVALID_CHARACTER_ERR: (self)
    170            If the medium contains characters that are invalid in the
    171            underlying style language.
    172          - NO_MODIFICATION_ALLOWED_ERR: (self)
    173            Raised if this list is readonly.
    174          """
    175          newMedium = self.__prepareset(newMedium)
    176
    177          if newMedium:
    178              mts = [self._normalize(mq.mediaType) for mq in self]
    179              newmt = self._normalize(newMedium.mediaType)
    180
    181              if newmt in mts:
    182                  self.deleteMedium(newmt)
    183                  self.seq.append(newMedium)
    184              elif u'all' == newmt:
    185                  # remove all except handheld (Opera)
    186                  h = None
    187                  for mq in self:
    188                      if mq.mediaType == u'handheld':
    189                          h = mq
    190                  del self[:]
    191                  self.seq.append(newMedium)
    192                  if h:
    193                      self.append(h)
    194              elif u'all' in mts:
    195                  if u'handheld' == newmt:
    196                      self.seq.append(newMedium)
    197              else:
    198                  self.seq.append(newMedium)
    199
    200              return True
    201
    202          else:
    203              return False
    204
    205 -    def append(self, newMedium):
    206          "overwrites ListSeq.append"
    207          self.appendMedium(newMedium)
    208
    209 -    def deleteMedium(self, oldMedium):
    210          """
    211          (DOM)
    212          Deletes the medium indicated by oldMedium from the list.
    213
    214          DOMException
    215
    216          - NO_MODIFICATION_ALLOWED_ERR: (self)
    217            Raised if this list is readonly.
    218          - NOT_FOUND_ERR: (self)
    219            Raised if oldMedium is not in the list.
    220          """
    221          self._checkReadonly()
    222          oldMedium = self._normalize(oldMedium)
    223
    224          for i, mq in enumerate(self):
    225              if self._normalize(mq.mediaType) == oldMedium:
    226                  del self[i]
    227                  break
    228          else:
    229              raise xml.dom.NotFoundErr(
    230                  u'"%s" not in this MediaList' % oldMedium)
    231
    232 -    def item(self, index):
    233          """
    234          (DOM)
    235          Returns the mediaType of the index'th element in the list.
    236          If index is greater than or equal to the number of media in the
    237          list, returns None.
    238          """
    239          try:
    240              return self[index].mediaType
    241          except IndexError:
    242              return None
    243
    244 -    def __repr__(self):
    245          return "cssutils.stylesheets.%s(mediaText=%r)" % (
    246                  self.__class__.__name__, self.mediaText)
    247
    248 -    def __str__(self):
    249          return "<cssutils.stylesheets.%s object mediaText=%r at 0x%x>" % (
    250                  self.__class__.__name__, self.mediaText, id(self))
    251