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