Show More
The requested changes are too big and content was truncated. Show full diff
@@ -0,0 +1,14 b'' | |||||
|
1 | # encoding: utf-8 | |||
|
2 | ||||
|
3 | __docformat__ = "restructuredtext en" | |||
|
4 | ||||
|
5 | #------------------------------------------------------------------------------- | |||
|
6 | # Copyright (C) 2008 The IPython Development Team | |||
|
7 | # | |||
|
8 | # Distributed under the terms of the BSD License. The full license is in | |||
|
9 | # the file COPYING, distributed as part of this software. | |||
|
10 | #------------------------------------------------------------------------------- | |||
|
11 | ||||
|
12 | #------------------------------------------------------------------------------- | |||
|
13 | # Imports | |||
|
14 | #------------------------------------------------------------------------------- No newline at end of file |
@@ -0,0 +1,99 b'' | |||||
|
1 | # encoding: utf-8 | |||
|
2 | ||||
|
3 | """This is the official entry point to IPython's configuration system. """ | |||
|
4 | ||||
|
5 | __docformat__ = "restructuredtext en" | |||
|
6 | ||||
|
7 | #------------------------------------------------------------------------------- | |||
|
8 | # Copyright (C) 2008 The IPython Development Team | |||
|
9 | # | |||
|
10 | # Distributed under the terms of the BSD License. The full license is in | |||
|
11 | # the file COPYING, distributed as part of this software. | |||
|
12 | #------------------------------------------------------------------------------- | |||
|
13 | ||||
|
14 | #------------------------------------------------------------------------------- | |||
|
15 | # Imports | |||
|
16 | #------------------------------------------------------------------------------- | |||
|
17 | ||||
|
18 | import os | |||
|
19 | from IPython.config.cutils import get_home_dir, get_ipython_dir | |||
|
20 | from IPython.external.configobj import ConfigObj | |||
|
21 | ||||
|
22 | class ConfigObjManager(object): | |||
|
23 | ||||
|
24 | def __init__(self, configObj, filename): | |||
|
25 | self.current = configObj | |||
|
26 | self.current.indent_type = ' ' | |||
|
27 | self.filename = filename | |||
|
28 | # self.write_default_config_file() | |||
|
29 | ||||
|
30 | def get_config_obj(self): | |||
|
31 | return self.current | |||
|
32 | ||||
|
33 | def update_config_obj(self, newConfig): | |||
|
34 | self.current.merge(newConfig) | |||
|
35 | ||||
|
36 | def update_config_obj_from_file(self, filename): | |||
|
37 | newConfig = ConfigObj(filename, file_error=False) | |||
|
38 | self.current.merge(newConfig) | |||
|
39 | ||||
|
40 | def update_config_obj_from_default_file(self, ipythondir=None): | |||
|
41 | fname = self.resolve_file_path(self.filename, ipythondir) | |||
|
42 | self.update_config_obj_from_file(fname) | |||
|
43 | ||||
|
44 | def write_config_obj_to_file(self, filename): | |||
|
45 | f = open(filename, 'w') | |||
|
46 | self.current.write(f) | |||
|
47 | f.close() | |||
|
48 | ||||
|
49 | def write_default_config_file(self): | |||
|
50 | ipdir = get_ipython_dir() | |||
|
51 | fname = ipdir + '/' + self.filename | |||
|
52 | if not os.path.isfile(fname): | |||
|
53 | print "Writing the configuration file to: " + fname | |||
|
54 | self.write_config_obj_to_file(fname) | |||
|
55 | ||||
|
56 | def _import(self, key): | |||
|
57 | package = '.'.join(key.split('.')[0:-1]) | |||
|
58 | obj = key.split('.')[-1] | |||
|
59 | execString = 'from %s import %s' % (package, obj) | |||
|
60 | exec execString | |||
|
61 | exec 'temp = %s' % obj | |||
|
62 | return temp | |||
|
63 | ||||
|
64 | def resolve_file_path(self, filename, ipythondir = None): | |||
|
65 | """Resolve filenames into absolute paths. | |||
|
66 | ||||
|
67 | This function looks in the following directories in order: | |||
|
68 | ||||
|
69 | 1. In the current working directory or by absolute path with ~ expanded | |||
|
70 | 2. In ipythondir if that is set | |||
|
71 | 3. In the IPYTHONDIR environment variable if it exists | |||
|
72 | 4. In the ~/.ipython directory | |||
|
73 | ||||
|
74 | Note: The IPYTHONDIR is also used by the trunk version of IPython so | |||
|
75 | changing it will also affect it was well. | |||
|
76 | """ | |||
|
77 | ||||
|
78 | # In cwd or by absolute path with ~ expanded | |||
|
79 | trythis = os.path.expanduser(filename) | |||
|
80 | if os.path.isfile(trythis): | |||
|
81 | return trythis | |||
|
82 | ||||
|
83 | # In ipythondir if it is set | |||
|
84 | if ipythondir is not None: | |||
|
85 | trythis = ipythondir + '/' + filename | |||
|
86 | if os.path.isfile(trythis): | |||
|
87 | return trythis | |||
|
88 | ||||
|
89 | trythis = get_ipython_dir() + '/' + filename | |||
|
90 | if os.path.isfile(trythis): | |||
|
91 | return trythis | |||
|
92 | ||||
|
93 | return None | |||
|
94 | ||||
|
95 | ||||
|
96 | ||||
|
97 | ||||
|
98 | ||||
|
99 |
@@ -0,0 +1,99 b'' | |||||
|
1 | # encoding: utf-8 | |||
|
2 | ||||
|
3 | """Configuration-related utilities for all IPython.""" | |||
|
4 | ||||
|
5 | __docformat__ = "restructuredtext en" | |||
|
6 | ||||
|
7 | #------------------------------------------------------------------------------- | |||
|
8 | # Copyright (C) 2008 The IPython Development Team | |||
|
9 | # | |||
|
10 | # Distributed under the terms of the BSD License. The full license is in | |||
|
11 | # the file COPYING, distributed as part of this software. | |||
|
12 | #------------------------------------------------------------------------------- | |||
|
13 | ||||
|
14 | #------------------------------------------------------------------------------- | |||
|
15 | # Imports | |||
|
16 | #------------------------------------------------------------------------------- | |||
|
17 | ||||
|
18 | import os | |||
|
19 | import sys | |||
|
20 | ||||
|
21 | #--------------------------------------------------------------------------- | |||
|
22 | # Normal code begins | |||
|
23 | #--------------------------------------------------------------------------- | |||
|
24 | ||||
|
25 | class HomeDirError(Exception): | |||
|
26 | pass | |||
|
27 | ||||
|
28 | def get_home_dir(): | |||
|
29 | """Return the closest possible equivalent to a 'home' directory. | |||
|
30 | ||||
|
31 | We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH. | |||
|
32 | ||||
|
33 | Currently only Posix and NT are implemented, a HomeDirError exception is | |||
|
34 | raised for all other OSes. """ | |||
|
35 | ||||
|
36 | isdir = os.path.isdir | |||
|
37 | env = os.environ | |||
|
38 | try: | |||
|
39 | homedir = env['HOME'] | |||
|
40 | if not isdir(homedir): | |||
|
41 | # in case a user stuck some string which does NOT resolve to a | |||
|
42 | # valid path, it's as good as if we hadn't foud it | |||
|
43 | raise KeyError | |||
|
44 | return homedir | |||
|
45 | except KeyError: | |||
|
46 | if os.name == 'posix': | |||
|
47 | raise HomeDirError,'undefined $HOME, IPython can not proceed.' | |||
|
48 | elif os.name == 'nt': | |||
|
49 | # For some strange reason, win9x returns 'nt' for os.name. | |||
|
50 | try: | |||
|
51 | homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH']) | |||
|
52 | if not isdir(homedir): | |||
|
53 | homedir = os.path.join(env['USERPROFILE']) | |||
|
54 | if not isdir(homedir): | |||
|
55 | raise HomeDirError | |||
|
56 | return homedir | |||
|
57 | except: | |||
|
58 | try: | |||
|
59 | # Use the registry to get the 'My Documents' folder. | |||
|
60 | import _winreg as wreg | |||
|
61 | key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, | |||
|
62 | "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders") | |||
|
63 | homedir = wreg.QueryValueEx(key,'Personal')[0] | |||
|
64 | key.Close() | |||
|
65 | if not isdir(homedir): | |||
|
66 | e = ('Invalid "Personal" folder registry key ' | |||
|
67 | 'typically "My Documents".\n' | |||
|
68 | 'Value: %s\n' | |||
|
69 | 'This is not a valid directory on your system.' % | |||
|
70 | homedir) | |||
|
71 | raise HomeDirError(e) | |||
|
72 | return homedir | |||
|
73 | except HomeDirError: | |||
|
74 | raise | |||
|
75 | except: | |||
|
76 | return 'C:\\' | |||
|
77 | elif os.name == 'dos': | |||
|
78 | # Desperate, may do absurd things in classic MacOS. May work under DOS. | |||
|
79 | return 'C:\\' | |||
|
80 | else: | |||
|
81 | raise HomeDirError,'support for your operating system not implemented.' | |||
|
82 | ||||
|
83 | def get_ipython_dir(): | |||
|
84 | ipdir_def = '.ipython' | |||
|
85 | home_dir = get_home_dir() | |||
|
86 | ipdir = os.path.abspath(os.environ.get('IPYTHONDIR', | |||
|
87 | os.path.join(home_dir,ipdir_def))) | |||
|
88 | return ipdir | |||
|
89 | ||||
|
90 | def import_item(key): | |||
|
91 | """ | |||
|
92 | Import and return bar given the string foo.bar. | |||
|
93 | """ | |||
|
94 | package = '.'.join(key.split('.')[0:-1]) | |||
|
95 | obj = key.split('.')[-1] | |||
|
96 | execString = 'from %s import %s' % (package, obj) | |||
|
97 | exec execString | |||
|
98 | exec 'temp = %s' % obj | |||
|
99 | return temp |
This diff has been collapsed as it changes many lines, (622 lines changed) Show them Hide them | |||||
@@ -0,0 +1,622 b'' | |||||
|
1 | # encoding: utf-8 | |||
|
2 | ||||
|
3 | """Mix of ConfigObj and Struct-like access. | |||
|
4 | ||||
|
5 | Provides: | |||
|
6 | ||||
|
7 | - Coupling a Struct object to a ConfigObj one, so that changes to the Traited | |||
|
8 | instance propagate back into the ConfigObj. | |||
|
9 | ||||
|
10 | - A declarative interface for describing configurations that automatically maps | |||
|
11 | to valid ConfigObj representations. | |||
|
12 | ||||
|
13 | - From these descriptions, valid .conf files can be auto-generated, with class | |||
|
14 | docstrings and traits information used for initial auto-documentation. | |||
|
15 | ||||
|
16 | - Hierarchical inclusion of files, so that a base config can be overridden only | |||
|
17 | in specific spots. | |||
|
18 | ||||
|
19 | ||||
|
20 | Notes: | |||
|
21 | ||||
|
22 | The file creation policy is: | |||
|
23 | ||||
|
24 | 1. Creating a SConfigManager(FooConfig,'missingfile.conf') will work | |||
|
25 | fine, and 'missingfile.conf' will be created empty. | |||
|
26 | ||||
|
27 | 2. Creating SConfigManager(FooConfig,'OKfile.conf') where OKfile.conf has | |||
|
28 | ||||
|
29 | include = 'missingfile.conf' | |||
|
30 | ||||
|
31 | conks out with IOError. | |||
|
32 | ||||
|
33 | My rationale is that creating top-level empty files is a common and | |||
|
34 | reasonable need, but that having invalid include statements should | |||
|
35 | raise an error right away, so people know immediately that their files | |||
|
36 | have gone stale. | |||
|
37 | ||||
|
38 | ||||
|
39 | TODO: | |||
|
40 | ||||
|
41 | - Turn the currently interactive tests into proper doc/unit tests. Complete | |||
|
42 | docstrings. | |||
|
43 | ||||
|
44 | - Write the real ipython1 config system using this. That one is more | |||
|
45 | complicated than either the MPL one or the fake 'ipythontest' that I wrote | |||
|
46 | here, and it requires solving the issue of declaring references to other | |||
|
47 | objects inside the config files. | |||
|
48 | ||||
|
49 | - [Low priority] Write a custom TraitsUI view so that hierarchical | |||
|
50 | configurations provide nicer interactive editing. The automatic system is | |||
|
51 | remarkably good, but for very complex configurations having a nicely | |||
|
52 | organized view would be nice. | |||
|
53 | """ | |||
|
54 | ||||
|
55 | __docformat__ = "restructuredtext en" | |||
|
56 | __license__ = 'BSD' | |||
|
57 | ||||
|
58 | #------------------------------------------------------------------------------- | |||
|
59 | # Copyright (C) 2008 The IPython Development Team | |||
|
60 | # | |||
|
61 | # Distributed under the terms of the BSD License. The full license is in | |||
|
62 | # the file COPYING, distributed as part of this software. | |||
|
63 | #------------------------------------------------------------------------------- | |||
|
64 | ||||
|
65 | #------------------------------------------------------------------------------- | |||
|
66 | # Imports | |||
|
67 | #------------------------------------------------------------------------------- | |||
|
68 | ||||
|
69 | ############################################################################ | |||
|
70 | # Stdlib imports | |||
|
71 | ############################################################################ | |||
|
72 | from cStringIO import StringIO | |||
|
73 | from inspect import isclass | |||
|
74 | ||||
|
75 | import os | |||
|
76 | import textwrap | |||
|
77 | ||||
|
78 | ############################################################################ | |||
|
79 | # External imports | |||
|
80 | ############################################################################ | |||
|
81 | ||||
|
82 | from IPython.external import configobj | |||
|
83 | ||||
|
84 | ############################################################################ | |||
|
85 | # Utility functions | |||
|
86 | ############################################################################ | |||
|
87 | ||||
|
88 | def get_split_ind(seq, N): | |||
|
89 | """seq is a list of words. Return the index into seq such that | |||
|
90 | len(' '.join(seq[:ind])<=N | |||
|
91 | """ | |||
|
92 | ||||
|
93 | sLen = 0 | |||
|
94 | # todo: use Alex's xrange pattern from the cbook for efficiency | |||
|
95 | for (word, ind) in zip(seq, range(len(seq))): | |||
|
96 | sLen += len(word) + 1 # +1 to account for the len(' ') | |||
|
97 | if sLen>=N: return ind | |||
|
98 | return len(seq) | |||
|
99 | ||||
|
100 | def wrap(prefix, text, cols, max_lines=6): | |||
|
101 | """'wrap text with prefix at length cols""" | |||
|
102 | pad = ' '*len(prefix.expandtabs()) | |||
|
103 | available = cols - len(pad) | |||
|
104 | ||||
|
105 | seq = text.split(' ') | |||
|
106 | Nseq = len(seq) | |||
|
107 | ind = 0 | |||
|
108 | lines = [] | |||
|
109 | while ind<Nseq: | |||
|
110 | lastInd = ind | |||
|
111 | ind += get_split_ind(seq[ind:], available) | |||
|
112 | lines.append(seq[lastInd:ind]) | |||
|
113 | ||||
|
114 | num_lines = len(lines) | |||
|
115 | abbr_end = max_lines // 2 | |||
|
116 | abbr_start = max_lines - abbr_end | |||
|
117 | lines_skipped = False | |||
|
118 | for i in range(num_lines): | |||
|
119 | if i == 0: | |||
|
120 | # add the prefix to the first line, pad with spaces otherwise | |||
|
121 | ret = prefix + ' '.join(lines[i]) + '\n' | |||
|
122 | elif i < abbr_start or i > num_lines-abbr_end-1: | |||
|
123 | ret += pad + ' '.join(lines[i]) + '\n' | |||
|
124 | else: | |||
|
125 | if not lines_skipped: | |||
|
126 | lines_skipped = True | |||
|
127 | ret += ' <...snipped %d lines...> \n' % (num_lines-max_lines) | |||
|
128 | # for line in lines[1:]: | |||
|
129 | # ret += pad + ' '.join(line) + '\n' | |||
|
130 | return ret[:-1] | |||
|
131 | ||||
|
132 | def dedent(txt): | |||
|
133 | """A modified version of textwrap.dedent, specialized for docstrings. | |||
|
134 | ||||
|
135 | This version doesn't get confused by the first line of text having | |||
|
136 | inconsistent indentation from the rest, which happens a lot in docstrings. | |||
|
137 | ||||
|
138 | :Examples: | |||
|
139 | ||||
|
140 | >>> s = ''' | |||
|
141 | ... First line. | |||
|
142 | ... More... | |||
|
143 | ... End''' | |||
|
144 | ||||
|
145 | >>> print dedent(s) | |||
|
146 | First line. | |||
|
147 | More... | |||
|
148 | End | |||
|
149 | ||||
|
150 | >>> s = '''First line | |||
|
151 | ... More... | |||
|
152 | ... End''' | |||
|
153 | ||||
|
154 | >>> print dedent(s) | |||
|
155 | First line | |||
|
156 | More... | |||
|
157 | End | |||
|
158 | """ | |||
|
159 | out = [textwrap.dedent(t) for t in txt.split('\n',1) | |||
|
160 | if t and not t.isspace()] | |||
|
161 | return '\n'.join(out) | |||
|
162 | ||||
|
163 | ||||
|
164 | def comment(strng,indent=''): | |||
|
165 | """return an input string, commented out""" | |||
|
166 | template = indent + '# %s' | |||
|
167 | lines = [template % s for s in strng.splitlines(True)] | |||
|
168 | return ''.join(lines) | |||
|
169 | ||||
|
170 | ||||
|
171 | def configobj2str(cobj): | |||
|
172 | """Dump a Configobj instance to a string.""" | |||
|
173 | outstr = StringIO() | |||
|
174 | cobj.write(outstr) | |||
|
175 | return outstr.getvalue() | |||
|
176 | ||||
|
177 | def get_config_filename(conf): | |||
|
178 | """Find the filename attribute of a ConfigObj given a sub-section object. | |||
|
179 | """ | |||
|
180 | depth = conf.depth | |||
|
181 | for d in range(depth): | |||
|
182 | conf = conf.parent | |||
|
183 | return conf.filename | |||
|
184 | ||||
|
185 | def sconf2File(sconf,fname,force=False): | |||
|
186 | """Write a SConfig instance to a given filename. | |||
|
187 | ||||
|
188 | :Keywords: | |||
|
189 | ||||
|
190 | force : bool (False) | |||
|
191 | If true, force writing even if the file exists. | |||
|
192 | """ | |||
|
193 | ||||
|
194 | if os.path.isfile(fname) and not force: | |||
|
195 | raise IOError("File %s already exists, use force=True to overwrite" % | |||
|
196 | fname) | |||
|
197 | ||||
|
198 | txt = repr(sconf) | |||
|
199 | ||||
|
200 | fobj = open(fname,'w') | |||
|
201 | fobj.write(txt) | |||
|
202 | fobj.close() | |||
|
203 | ||||
|
204 | def filter_scalars(sc): | |||
|
205 | """ input sc MUST be sorted!!!""" | |||
|
206 | scalars = [] | |||
|
207 | maxi = len(sc)-1 | |||
|
208 | i = 0 | |||
|
209 | while i<len(sc): | |||
|
210 | t = sc[i] | |||
|
211 | if t.startswith('_sconf_'): | |||
|
212 | # Skip altogether private _sconf_ attributes, so we actually issue | |||
|
213 | # a 'continue' call to avoid the append(t) below | |||
|
214 | i += 1 | |||
|
215 | continue | |||
|
216 | scalars.append(t) | |||
|
217 | i += 1 | |||
|
218 | ||||
|
219 | return scalars | |||
|
220 | ||||
|
221 | ||||
|
222 | def get_scalars(obj): | |||
|
223 | """Return scalars for a Sconf class object""" | |||
|
224 | ||||
|
225 | skip = set(['trait_added','trait_modified']) | |||
|
226 | sc = [k for k in obj.__dict__ if not k.startswith('_')] | |||
|
227 | sc.sort() | |||
|
228 | return filter_scalars(sc) | |||
|
229 | ||||
|
230 | ||||
|
231 | def get_sections(obj,sectionClass): | |||
|
232 | """Return sections for a Sconf class object""" | |||
|
233 | return [(n,v) for (n,v) in obj.__dict__.iteritems() | |||
|
234 | if isclass(v) and issubclass(v,sectionClass)] | |||
|
235 | ||||
|
236 | ||||
|
237 | def get_instance_sections(inst): | |||
|
238 | """Return sections for a Sconf instance""" | |||
|
239 | sections = [(k,v) for k,v in inst.__dict__.iteritems() | |||
|
240 | if isinstance(v,SConfig) and not k=='_sconf_parent'] | |||
|
241 | # Sort the sections by name | |||
|
242 | sections.sort(key=lambda x:x[0]) | |||
|
243 | return sections | |||
|
244 | ||||
|
245 | ||||
|
246 | def partition_instance(obj): | |||
|
247 | """Return scalars,sections for a given Sconf instance. | |||
|
248 | """ | |||
|
249 | scnames = [] | |||
|
250 | sections = [] | |||
|
251 | for k,v in obj.__dict__.iteritems(): | |||
|
252 | if isinstance(v,SConfig): | |||
|
253 | if not k=='_sconf_parent': | |||
|
254 | sections.append((k,v)) | |||
|
255 | else: | |||
|
256 | scnames.append(k) | |||
|
257 | ||||
|
258 | # Sort the sections by name | |||
|
259 | sections.sort(key=lambda x:x[0]) | |||
|
260 | ||||
|
261 | # Sort the scalar names, filter them and then extract the actual objects | |||
|
262 | scnames.sort() | |||
|
263 | scnames = filter_scalars(scnames) | |||
|
264 | scalars = [(s,obj.__dict__[s]) for s in scnames] | |||
|
265 | ||||
|
266 | return scalars, sections | |||
|
267 | ||||
|
268 | ||||
|
269 | def mk_ConfigObj(filename,mk_missing_file=True): | |||
|
270 | """Return a ConfigObj instance with our hardcoded conventions. | |||
|
271 | ||||
|
272 | Use a simple factory that wraps our option choices for using ConfigObj. | |||
|
273 | I'm hard-wiring certain choices here, so we'll always use instances with | |||
|
274 | THESE choices. | |||
|
275 | ||||
|
276 | :Parameters: | |||
|
277 | ||||
|
278 | filename : string | |||
|
279 | File to read from. | |||
|
280 | ||||
|
281 | :Keywords: | |||
|
282 | makeMissingFile : bool (True) | |||
|
283 | If true, the file named by `filename` may not yet exist and it will be | |||
|
284 | automatically created (empty). Else, if `filename` doesn't exist, an | |||
|
285 | IOError will be raised. | |||
|
286 | """ | |||
|
287 | ||||
|
288 | if mk_missing_file: | |||
|
289 | create_empty = True | |||
|
290 | file_error = False | |||
|
291 | else: | |||
|
292 | create_empty = False | |||
|
293 | file_error = True | |||
|
294 | ||||
|
295 | return configobj.ConfigObj(filename, | |||
|
296 | create_empty=create_empty, | |||
|
297 | file_error=file_error, | |||
|
298 | indent_type=' ', | |||
|
299 | interpolation='Template', | |||
|
300 | unrepr=True) | |||
|
301 | ||||
|
302 | nullConf = mk_ConfigObj(None) | |||
|
303 | ||||
|
304 | ||||
|
305 | class RecursiveConfigObj(object): | |||
|
306 | """Object-oriented interface for recursive ConfigObj constructions.""" | |||
|
307 | ||||
|
308 | def __init__(self,filename): | |||
|
309 | """Return a ConfigObj instance with our hardcoded conventions. | |||
|
310 | ||||
|
311 | Use a simple factory that wraps our option choices for using ConfigObj. | |||
|
312 | I'm hard-wiring certain choices here, so we'll always use instances with | |||
|
313 | THESE choices. | |||
|
314 | ||||
|
315 | :Parameters: | |||
|
316 | ||||
|
317 | filename : string | |||
|
318 | File to read from. | |||
|
319 | """ | |||
|
320 | ||||
|
321 | self.comp = [] | |||
|
322 | self.conf = self._load(filename) | |||
|
323 | ||||
|
324 | def _load(self,filename,mk_missing_file=True): | |||
|
325 | conf = mk_ConfigObj(filename,mk_missing_file) | |||
|
326 | ||||
|
327 | # Do recursive loading. We only allow (or at least honor) the include | |||
|
328 | # tag at the top-level. For now, we drop the inclusion information so | |||
|
329 | # that there are no restrictions on which levels of the SConfig | |||
|
330 | # hierarchy can use include statements. But this means that | |||
|
331 | ||||
|
332 | # if bookkeeping of each separate component of the recursive | |||
|
333 | # construction was requested, make a separate object for storage | |||
|
334 | # there, since we don't want that to be modified by the inclusion | |||
|
335 | # process. | |||
|
336 | self.comp.append(mk_ConfigObj(filename,mk_missing_file)) | |||
|
337 | ||||
|
338 | incfname = conf.pop('include',None) | |||
|
339 | if incfname is not None: | |||
|
340 | # Do recursive load. We don't want user includes that point to | |||
|
341 | # missing files to fail silently, so in the recursion we disable | |||
|
342 | # auto-creation of missing files. | |||
|
343 | confinc = self._load(incfname,mk_missing_file=False) | |||
|
344 | ||||
|
345 | # Update with self to get proper ordering (included files provide | |||
|
346 | # base data, current one overwrites) | |||
|
347 | confinc.update(conf) | |||
|
348 | # And do swap to return the updated structure | |||
|
349 | conf = confinc | |||
|
350 | # Set the filename to be the original file instead of the included | |||
|
351 | # one | |||
|
352 | conf.filename = filename | |||
|
353 | return conf | |||
|
354 | ||||
|
355 | ############################################################################ | |||
|
356 | # Main SConfig class and supporting exceptions | |||
|
357 | ############################################################################ | |||
|
358 | ||||
|
359 | class SConfigError(Exception): pass | |||
|
360 | ||||
|
361 | class SConfigInvalidKeyError(SConfigError): pass | |||
|
362 | ||||
|
363 | class SConfig(object): | |||
|
364 | """A class representing configuration objects. | |||
|
365 | ||||
|
366 | Note: this class should NOT have any traits itself, since the actual traits | |||
|
367 | will be declared by subclasses. This class is meant to ONLY declare the | |||
|
368 | necessary initialization/validation methods. """ | |||
|
369 | ||||
|
370 | # Any traits declared here are prefixed with _sconf_ so that our special | |||
|
371 | # formatting/analysis utilities can distinguish them from user traits and | |||
|
372 | # can avoid them. | |||
|
373 | ||||
|
374 | # Once created, the tree's hierarchy can NOT be modified | |||
|
375 | _sconf_parent = None | |||
|
376 | ||||
|
377 | def __init__(self,config=None,parent=None,monitor=None): | |||
|
378 | """Makes an SConfig object out of a ConfigObj instance | |||
|
379 | """ | |||
|
380 | ||||
|
381 | if config is None: | |||
|
382 | config = mk_ConfigObj(None) | |||
|
383 | ||||
|
384 | # Validate the set of scalars ... | |||
|
385 | my_scalars = set(get_scalars(self)) | |||
|
386 | cf_scalars = set(config.scalars) | |||
|
387 | invalid_scalars = cf_scalars - my_scalars | |||
|
388 | if invalid_scalars: | |||
|
389 | config_fname = get_config_filename(config) | |||
|
390 | m=("In config defined in file: %r\n" | |||
|
391 | "Error processing section: %s\n" | |||
|
392 | "These keys are invalid : %s\n" | |||
|
393 | "Valid key names : %s\n" | |||
|
394 | % (config_fname,self.__class__.__name__, | |||
|
395 | list(invalid_scalars),list(my_scalars))) | |||
|
396 | raise SConfigInvalidKeyError(m) | |||
|
397 | ||||
|
398 | # ... and sections | |||
|
399 | section_items = get_sections(self.__class__,SConfig) | |||
|
400 | my_sections = set([n for n,v in section_items]) | |||
|
401 | cf_sections = set(config.sections) | |||
|
402 | invalid_sections = cf_sections - my_sections | |||
|
403 | if invalid_sections: | |||
|
404 | config_fname = get_config_filename(config) | |||
|
405 | m = ("In config defined in file: %r\n" | |||
|
406 | "Error processing section: %s\n" | |||
|
407 | "These subsections are invalid : %s\n" | |||
|
408 | "Valid subsection names : %s\n" | |||
|
409 | % (config_fname,self.__class__.__name__, | |||
|
410 | list(invalid_sections),list(my_sections))) | |||
|
411 | raise SConfigInvalidKeyError(m) | |||
|
412 | ||||
|
413 | self._sconf_parent = parent | |||
|
414 | ||||
|
415 | # Now set the traits based on the config | |||
|
416 | for k in my_scalars: | |||
|
417 | setattr(self,k,config[k]) | |||
|
418 | ||||
|
419 | # And build subsections | |||
|
420 | for s,v in section_items: | |||
|
421 | sec_config = config.setdefault(s,{}) | |||
|
422 | section = v(sec_config,self,monitor=monitor) | |||
|
423 | ||||
|
424 | # We must use add_trait instead of setattr because we inherit from | |||
|
425 | # HasStrictTraits, but we need to then do a 'dummy' getattr call on | |||
|
426 | # self so the class trait propagates to the instance. | |||
|
427 | self.add_trait(s,section) | |||
|
428 | getattr(self,s) | |||
|
429 | ||||
|
430 | def __repr__(self,depth=0): | |||
|
431 | """Dump a section to a string.""" | |||
|
432 | ||||
|
433 | indent = ' '*(depth) | |||
|
434 | ||||
|
435 | top_name = self.__class__.__name__ | |||
|
436 | ||||
|
437 | if depth == 0: | |||
|
438 | label = '# %s - plaintext (in .conf format)\n' % top_name | |||
|
439 | else: | |||
|
440 | # Section titles are indented one level less than their contents in | |||
|
441 | # the ConfigObj write methods. | |||
|
442 | sec_indent = ' '*(depth-1) | |||
|
443 | label = '\n'+sec_indent+('[' * depth) + top_name + (']'*depth) | |||
|
444 | ||||
|
445 | out = [label] | |||
|
446 | ||||
|
447 | doc = self.__class__.__doc__ | |||
|
448 | if doc is not None: | |||
|
449 | out.append(comment(dedent(doc),indent)) | |||
|
450 | ||||
|
451 | scalars, sections = partition_instance(self) | |||
|
452 | ||||
|
453 | for s,v in scalars: | |||
|
454 | try: | |||
|
455 | info = self.__base_traits__[s].handler.info() | |||
|
456 | # Get a short version of info with lines of max. 78 chars, so | |||
|
457 | # that after commenting them out (with '# ') they are at most | |||
|
458 | # 80-chars long. | |||
|
459 | out.append(comment(wrap('',info.replace('\n', ' '),78-len(indent)),indent)) | |||
|
460 | except (KeyError,AttributeError): | |||
|
461 | pass | |||
|
462 | out.append(indent+('%s = %r' % (s,v))) | |||
|
463 | ||||
|
464 | for sname,sec in sections: | |||
|
465 | out.append(sec.__repr__(depth+1)) | |||
|
466 | ||||
|
467 | return '\n'.join(out) | |||
|
468 | ||||
|
469 | def __str__(self): | |||
|
470 | return self.__class__.__name__ | |||
|
471 | ||||
|
472 | ||||
|
473 | ############################################################################## | |||
|
474 | # High-level class(es) and utilities for handling a coupled pair of SConfig and | |||
|
475 | # ConfigObj instances. | |||
|
476 | ############################################################################## | |||
|
477 | ||||
|
478 | def path_to_root(obj): | |||
|
479 | """Find the path to the root of a nested SConfig instance.""" | |||
|
480 | ob = obj | |||
|
481 | path = [] | |||
|
482 | while ob._sconf_parent is not None: | |||
|
483 | path.append(ob.__class__.__name__) | |||
|
484 | ob = ob._sconf_parent | |||
|
485 | path.reverse() | |||
|
486 | return path | |||
|
487 | ||||
|
488 | ||||
|
489 | def set_value(fconf,path,key,value): | |||
|
490 | """Set a value on a ConfigObj instance, arbitrarily deep.""" | |||
|
491 | section = fconf | |||
|
492 | for sname in path: | |||
|
493 | section = section.setdefault(sname,{}) | |||
|
494 | section[key] = value | |||
|
495 | ||||
|
496 | ||||
|
497 | def fmonitor(fconf): | |||
|
498 | """Make a monitor for coupling SConfig instances to ConfigObj ones. | |||
|
499 | ||||
|
500 | We must use a closure because Traits makes assumptions about the functions | |||
|
501 | used with on_trait_change() that prevent the use of a callable instance. | |||
|
502 | """ | |||
|
503 | ||||
|
504 | def mon(obj,name,new): | |||
|
505 | #print 'OBJ:',obj # dbg | |||
|
506 | #print 'NAM:',name # dbg | |||
|
507 | #print 'NEW:',new # dbg | |||
|
508 | set_value(fconf,path_to_root(obj),name,new) | |||
|
509 | ||||
|
510 | return mon | |||
|
511 | ||||
|
512 | ||||
|
513 | class SConfigManager(object): | |||
|
514 | """A simple object to manage and sync a SConfig and a ConfigObj pair. | |||
|
515 | """ | |||
|
516 | ||||
|
517 | def __init__(self,configClass,configFilename,filePriority=True): | |||
|
518 | """Make a new SConfigManager. | |||
|
519 | ||||
|
520 | :Parameters: | |||
|
521 | ||||
|
522 | configClass : class | |||
|
523 | ||||
|
524 | configFilename : string | |||
|
525 | If the filename points to a non-existent file, it will be created | |||
|
526 | empty. This is useful when creating a file form from an existing | |||
|
527 | configClass with the class defaults. | |||
|
528 | ||||
|
529 | ||||
|
530 | :Keywords: | |||
|
531 | ||||
|
532 | filePriority : bool (True) | |||
|
533 | ||||
|
534 | If true, at construction time the file object takes priority and | |||
|
535 | overwrites the contents of the config object. Else, the data flow | |||
|
536 | is reversed and the file object will be overwritten with the | |||
|
537 | configClass defaults at write() time. | |||
|
538 | """ | |||
|
539 | ||||
|
540 | rconf = RecursiveConfigObj(configFilename) | |||
|
541 | # In a hierarchical object, the two following fconfs are *very* | |||
|
542 | # different. In self.fconf, we'll keep the outer-most fconf associated | |||
|
543 | # directly to the original filename. self.fconf_combined, instead, | |||
|
544 | # contains an object which has the combined effect of having merged all | |||
|
545 | # the called files in the recursive chain. | |||
|
546 | self.fconf = rconf.comp[0] | |||
|
547 | self.fconf_combined = rconf.conf | |||
|
548 | ||||
|
549 | # Create a monitor to track and apply trait changes to the sconf | |||
|
550 | # instance over into the fconf one | |||
|
551 | monitor = fmonitor(self.fconf) | |||
|
552 | ||||
|
553 | if filePriority: | |||
|
554 | self.sconf = configClass(self.fconf_combined,monitor=monitor) | |||
|
555 | else: | |||
|
556 | # Push defaults onto file object | |||
|
557 | self.sconf = configClass(mk_ConfigObj(None),monitor=monitor) | |||
|
558 | self.fconfUpdate(self.fconf,self.sconf) | |||
|
559 | ||||
|
560 | def fconfUpdate(self,fconf,sconf): | |||
|
561 | """Update the fconf object with the data from sconf""" | |||
|
562 | ||||
|
563 | scalars, sections = partition_instance(sconf) | |||
|
564 | ||||
|
565 | for s,v in scalars: | |||
|
566 | fconf[s] = v | |||
|
567 | ||||
|
568 | for secname,sec in sections: | |||
|
569 | self.fconfUpdate(fconf.setdefault(secname,{}),sec) | |||
|
570 | ||||
|
571 | def write(self,filename=None): | |||
|
572 | """Write out to disk. | |||
|
573 | ||||
|
574 | This method writes out only to the top file in a hierarchical | |||
|
575 | configuration, which means that the class defaults and other values not | |||
|
576 | explicitly set in the top level file are NOT written out. | |||
|
577 | ||||
|
578 | :Keywords: | |||
|
579 | ||||
|
580 | filename : string (None) | |||
|
581 | If given, the output is written to this file, otherwise the | |||
|
582 | .filename attribute of the top-level configuration object is used. | |||
|
583 | """ | |||
|
584 | if filename is not None: | |||
|
585 | file_obj = open(filename,'w') | |||
|
586 | out = self.fconf.write(file_obj) | |||
|
587 | file_obj.close() | |||
|
588 | return out | |||
|
589 | else: | |||
|
590 | return self.fconf.write() | |||
|
591 | ||||
|
592 | def writeAll(self,filename=None): | |||
|
593 | """Write out the entire configuration to disk. | |||
|
594 | ||||
|
595 | This method, in contrast with write(), updates the .fconf_combined | |||
|
596 | object with the *entire* .sconf instance, and then writes it out to | |||
|
597 | disk. This method is thus useful for generating files that have a | |||
|
598 | self-contained, non-hierarchical file. | |||
|
599 | ||||
|
600 | :Keywords: | |||
|
601 | ||||
|
602 | filename : string (None) | |||
|
603 | If given, the output is written to this file, otherwise the | |||
|
604 | .filename attribute of the top-level configuration object is used. | |||
|
605 | """ | |||
|
606 | if filename is not None: | |||
|
607 | file_obj = open(filename,'w') | |||
|
608 | self.fconfUpdate(self.fconf_combined,self.sconf) | |||
|
609 | out = self.fconf_combined.write(file_obj) | |||
|
610 | file_obj.close() | |||
|
611 | return out | |||
|
612 | else: | |||
|
613 | self.fconfUpdate(self.fconf_combined,self.sconf) | |||
|
614 | return self.fconf_combined.write() | |||
|
615 | ||||
|
616 | def sconf_str(self): | |||
|
617 | return str(self.sconf) | |||
|
618 | ||||
|
619 | def fconf_str(self): | |||
|
620 | return configobj2str(self.fconf) | |||
|
621 | ||||
|
622 | __repr__ = __str__ = fconf_str |
@@ -0,0 +1,37 b'' | |||||
|
1 | """Little utilities for testing tconfig. | |||
|
2 | ||||
|
3 | This module is meant to be used via | |||
|
4 | ||||
|
5 | import sctst; reload(sctst) | |||
|
6 | from sctst import * | |||
|
7 | ||||
|
8 | at the top of the actual test scripts, so that they all get the entire set of | |||
|
9 | common test tools with minimal fuss. | |||
|
10 | """ | |||
|
11 | ||||
|
12 | # Standard library imports | |||
|
13 | import os | |||
|
14 | import sys | |||
|
15 | from pprint import pprint | |||
|
16 | ||||
|
17 | # Our own imports. | |||
|
18 | ||||
|
19 | from IPython.config import sconfig | |||
|
20 | reload(sconfig) | |||
|
21 | ||||
|
22 | from sconfig import mkConfigObj, RecursiveConfigObj, SConfigManager, \ | |||
|
23 | sconf2file | |||
|
24 | ||||
|
25 | # Simple utilities/classes for testing | |||
|
26 | ||||
|
27 | def cat(fname): | |||
|
28 | print '### FILENAME:',fname | |||
|
29 | print open(fname).read() | |||
|
30 | ||||
|
31 | ||||
|
32 | class App(object): | |||
|
33 | """A trivial 'application' class to be initialized. | |||
|
34 | """ | |||
|
35 | def __init__(self,config_class,config_filename): | |||
|
36 | self.rcman = SConfigManager(config_class,config_filename) | |||
|
37 | self.rc = self.rcman.sconf |
@@ -0,0 +1,14 b'' | |||||
|
1 | # Toy example of a TConfig-based configuration description | |||
|
2 | ||||
|
3 | # This is the class declaration for the configuration: | |||
|
4 | ||||
|
5 | # SimpleConfig | |||
|
6 | # Configuration for my application | |||
|
7 | ||||
|
8 | solver = "Iterative2" | |||
|
9 | ||||
|
10 | [Protocol] | |||
|
11 | # Specify the Protocol | |||
|
12 | ||||
|
13 | ptype = "http2" | |||
|
14 | max_users = 4 |
@@ -0,0 +1,14 b'' | |||||
|
1 | # Toy example of a TConfig-based configuration description | |||
|
2 | ||||
|
3 | # This is the class declaration for the configuration: | |||
|
4 | ||||
|
5 | # SimpleConfig | |||
|
6 | # Configuration for my application | |||
|
7 | ||||
|
8 | datafile = string(default='data.txt') | |||
|
9 | solver = option('Direct','Iterative') | |||
|
10 | ||||
|
11 | [Protocol] | |||
|
12 | # Specify the Protocol | |||
|
13 | ptype = option('http','ftp','ssh') | |||
|
14 | max_users = integer(1,10) |
@@ -0,0 +1,59 b'' | |||||
|
1 | """Toy example of reading an SConf object.""" | |||
|
2 | ||||
|
3 | from IPython.external.configobj import ConfigObj | |||
|
4 | from IPython.external import configobj, validate | |||
|
5 | ||||
|
6 | ||||
|
7 | from IPython.config import sconfig | |||
|
8 | reload(sconfig) | |||
|
9 | ||||
|
10 | configspecfilename = 'simple.spec.conf' | |||
|
11 | filename = 'simple.conf' | |||
|
12 | ||||
|
13 | print '*'*80 | |||
|
14 | configspec = ConfigObj(configspecfilename, encoding='UTF8', | |||
|
15 | list_values=False) | |||
|
16 | print sconfig.configobj2str(configspec) | |||
|
17 | ||||
|
18 | print '*'*80 | |||
|
19 | config = ConfigObj(filename, configspec=configspec, | |||
|
20 | interpolation='Template', | |||
|
21 | unrepr=True) | |||
|
22 | print sconfig.configobj2str(config) | |||
|
23 | vdt = validate.Validator() | |||
|
24 | test = config.validate(vdt,preserve_errors=True) | |||
|
25 | ||||
|
26 | #### | |||
|
27 | vdt = validate.Validator() | |||
|
28 | class Bunch: pass | |||
|
29 | vf = Bunch() | |||
|
30 | vf.__dict__.update(vdt.functions) | |||
|
31 | vf.pass_ = vdt.functions['pass'] | |||
|
32 | vf.__dict__.pop('',None) | |||
|
33 | vf.__dict__.pop('pass',None) | |||
|
34 | ### | |||
|
35 | ||||
|
36 | ||||
|
37 | if test==True: | |||
|
38 | print 'All OK' | |||
|
39 | else: | |||
|
40 | err = configobj.flatten_errors(config,test) | |||
|
41 | print 'Flat errors:' | |||
|
42 | for secs,key,result in err: | |||
|
43 | if secs == []: | |||
|
44 | print 'DEFAULT:','key:',key,'err:',result | |||
|
45 | else: | |||
|
46 | print 'Secs:',secs,'key:',key,'err:',result | |||
|
47 | ||||
|
48 | ||||
|
49 | ## | |||
|
50 | print '*'*80 | |||
|
51 | ||||
|
52 | sc = sconfig.SConfig(configspecfilename) | |||
|
53 | ||||
|
54 | ||||
|
55 | ||||
|
56 | #### | |||
|
57 | ||||
|
58 | ||||
|
59 |
@@ -0,0 +1,278 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | """String interpolation for Python (by Ka-Ping Yee, 14 Feb 2000). | |||
|
3 | ||||
|
4 | This module lets you quickly and conveniently interpolate values into | |||
|
5 | strings (in the flavour of Perl or Tcl, but with less extraneous | |||
|
6 | punctuation). You get a bit more power than in the other languages, | |||
|
7 | because this module allows subscripting, slicing, function calls, | |||
|
8 | attribute lookup, or arbitrary expressions. Variables and expressions | |||
|
9 | are evaluated in the namespace of the caller. | |||
|
10 | ||||
|
11 | The itpl() function returns the result of interpolating a string, and | |||
|
12 | printpl() prints out an interpolated string. Here are some examples: | |||
|
13 | ||||
|
14 | from Itpl import printpl | |||
|
15 | printpl("Here is a $string.") | |||
|
16 | printpl("Here is a $module.member.") | |||
|
17 | printpl("Here is an $object.member.") | |||
|
18 | printpl("Here is a $functioncall(with, arguments).") | |||
|
19 | printpl("Here is an ${arbitrary + expression}.") | |||
|
20 | printpl("Here is an $array[3] member.") | |||
|
21 | printpl("Here is a $dictionary['member'].") | |||
|
22 | ||||
|
23 | The filter() function filters a file object so that output through it | |||
|
24 | is interpolated. This lets you produce the illusion that Python knows | |||
|
25 | how to do interpolation: | |||
|
26 | ||||
|
27 | import Itpl | |||
|
28 | sys.stdout = Itpl.filter() | |||
|
29 | f = "fancy" | |||
|
30 | print "Isn't this $f?" | |||
|
31 | print "Standard output has been replaced with a $sys.stdout object." | |||
|
32 | sys.stdout = Itpl.unfilter() | |||
|
33 | print "Okay, back $to $normal." | |||
|
34 | ||||
|
35 | Under the hood, the Itpl class represents a string that knows how to | |||
|
36 | interpolate values. An instance of the class parses the string once | |||
|
37 | upon initialization; the evaluation and substitution can then be done | |||
|
38 | each time the instance is evaluated with str(instance). For example: | |||
|
39 | ||||
|
40 | from Itpl import Itpl | |||
|
41 | s = Itpl("Here is $foo.") | |||
|
42 | foo = 5 | |||
|
43 | print str(s) | |||
|
44 | foo = "bar" | |||
|
45 | print str(s) | |||
|
46 | ||||
|
47 | $Id: Itpl.py 2305 2007-05-04 05:34:42Z bgranger $ | |||
|
48 | """ # ' -> close an open quote for stupid emacs | |||
|
49 | ||||
|
50 | #***************************************************************************** | |||
|
51 | # | |||
|
52 | # Copyright (c) 2001 Ka-Ping Yee <ping@lfw.org> | |||
|
53 | # | |||
|
54 | # | |||
|
55 | # Published under the terms of the MIT license, hereby reproduced: | |||
|
56 | # | |||
|
57 | # Permission is hereby granted, free of charge, to any person obtaining a copy | |||
|
58 | # of this software and associated documentation files (the "Software"), to | |||
|
59 | # deal in the Software without restriction, including without limitation the | |||
|
60 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |||
|
61 | # sell copies of the Software, and to permit persons to whom the Software is | |||
|
62 | # furnished to do so, subject to the following conditions: | |||
|
63 | # | |||
|
64 | # The above copyright notice and this permission notice shall be included in | |||
|
65 | # all copies or substantial portions of the Software. | |||
|
66 | # | |||
|
67 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
|
68 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
|
69 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
|
70 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
|
71 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
|
72 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |||
|
73 | # IN THE SOFTWARE. | |||
|
74 | # | |||
|
75 | #***************************************************************************** | |||
|
76 | ||||
|
77 | __author__ = 'Ka-Ping Yee <ping@lfw.org>' | |||
|
78 | __license__ = 'MIT' | |||
|
79 | ||||
|
80 | import string | |||
|
81 | import sys | |||
|
82 | from tokenize import tokenprog | |||
|
83 | from types import StringType | |||
|
84 | ||||
|
85 | class ItplError(ValueError): | |||
|
86 | def __init__(self, text, pos): | |||
|
87 | self.text = text | |||
|
88 | self.pos = pos | |||
|
89 | def __str__(self): | |||
|
90 | return "unfinished expression in %s at char %d" % ( | |||
|
91 | repr(self.text), self.pos) | |||
|
92 | ||||
|
93 | def matchorfail(text, pos): | |||
|
94 | match = tokenprog.match(text, pos) | |||
|
95 | if match is None: | |||
|
96 | raise ItplError(text, pos) | |||
|
97 | return match, match.end() | |||
|
98 | ||||
|
99 | class Itpl: | |||
|
100 | """Class representing a string with interpolation abilities. | |||
|
101 | ||||
|
102 | Upon creation, an instance works out what parts of the format | |||
|
103 | string are literal and what parts need to be evaluated. The | |||
|
104 | evaluation and substitution happens in the namespace of the | |||
|
105 | caller when str(instance) is called.""" | |||
|
106 | ||||
|
107 | def __init__(self, format,codec='utf_8',encoding_errors='backslashreplace'): | |||
|
108 | """The single mandatory argument to this constructor is a format | |||
|
109 | string. | |||
|
110 | ||||
|
111 | The format string is parsed according to the following rules: | |||
|
112 | ||||
|
113 | 1. A dollar sign and a name, possibly followed by any of: | |||
|
114 | - an open-paren, and anything up to the matching paren | |||
|
115 | - an open-bracket, and anything up to the matching bracket | |||
|
116 | - a period and a name | |||
|
117 | any number of times, is evaluated as a Python expression. | |||
|
118 | ||||
|
119 | 2. A dollar sign immediately followed by an open-brace, and | |||
|
120 | anything up to the matching close-brace, is evaluated as | |||
|
121 | a Python expression. | |||
|
122 | ||||
|
123 | 3. Outside of the expressions described in the above two rules, | |||
|
124 | two dollar signs in a row give you one literal dollar sign. | |||
|
125 | ||||
|
126 | Optional arguments: | |||
|
127 | ||||
|
128 | - codec('utf_8'): a string containing the name of a valid Python | |||
|
129 | codec. | |||
|
130 | ||||
|
131 | - encoding_errors('backslashreplace'): a string with a valid error handling | |||
|
132 | policy. See the codecs module documentation for details. | |||
|
133 | ||||
|
134 | These are used to encode the format string if a call to str() fails on | |||
|
135 | the expanded result.""" | |||
|
136 | ||||
|
137 | if not isinstance(format,basestring): | |||
|
138 | raise TypeError, "needs string initializer" | |||
|
139 | self.format = format | |||
|
140 | self.codec = codec | |||
|
141 | self.encoding_errors = encoding_errors | |||
|
142 | ||||
|
143 | namechars = "abcdefghijklmnopqrstuvwxyz" \ | |||
|
144 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; | |||
|
145 | chunks = [] | |||
|
146 | pos = 0 | |||
|
147 | ||||
|
148 | while 1: | |||
|
149 | dollar = string.find(format, "$", pos) | |||
|
150 | if dollar < 0: break | |||
|
151 | nextchar = format[dollar+1] | |||
|
152 | ||||
|
153 | if nextchar == "{": | |||
|
154 | chunks.append((0, format[pos:dollar])) | |||
|
155 | pos, level = dollar+2, 1 | |||
|
156 | while level: | |||
|
157 | match, pos = matchorfail(format, pos) | |||
|
158 | tstart, tend = match.regs[3] | |||
|
159 | token = format[tstart:tend] | |||
|
160 | if token == "{": level = level+1 | |||
|
161 | elif token == "}": level = level-1 | |||
|
162 | chunks.append((1, format[dollar+2:pos-1])) | |||
|
163 | ||||
|
164 | elif nextchar in namechars: | |||
|
165 | chunks.append((0, format[pos:dollar])) | |||
|
166 | match, pos = matchorfail(format, dollar+1) | |||
|
167 | while pos < len(format): | |||
|
168 | if format[pos] == "." and \ | |||
|
169 | pos+1 < len(format) and format[pos+1] in namechars: | |||
|
170 | match, pos = matchorfail(format, pos+1) | |||
|
171 | elif format[pos] in "([": | |||
|
172 | pos, level = pos+1, 1 | |||
|
173 | while level: | |||
|
174 | match, pos = matchorfail(format, pos) | |||
|
175 | tstart, tend = match.regs[3] | |||
|
176 | token = format[tstart:tend] | |||
|
177 | if token[0] in "([": level = level+1 | |||
|
178 | elif token[0] in ")]": level = level-1 | |||
|
179 | else: break | |||
|
180 | chunks.append((1, format[dollar+1:pos])) | |||
|
181 | ||||
|
182 | else: | |||
|
183 | chunks.append((0, format[pos:dollar+1])) | |||
|
184 | pos = dollar + 1 + (nextchar == "$") | |||
|
185 | ||||
|
186 | if pos < len(format): chunks.append((0, format[pos:])) | |||
|
187 | self.chunks = chunks | |||
|
188 | ||||
|
189 | def __repr__(self): | |||
|
190 | return "<Itpl %s >" % repr(self.format) | |||
|
191 | ||||
|
192 | def _str(self,glob,loc): | |||
|
193 | """Evaluate to a string in the given globals/locals. | |||
|
194 | ||||
|
195 | The final output is built by calling str(), but if this fails, the | |||
|
196 | result is encoded with the instance's codec and error handling policy, | |||
|
197 | via a call to out.encode(self.codec,self.encoding_errors)""" | |||
|
198 | result = [] | |||
|
199 | app = result.append | |||
|
200 | for live, chunk in self.chunks: | |||
|
201 | if live: app(str(eval(chunk,glob,loc))) | |||
|
202 | else: app(chunk) | |||
|
203 | out = ''.join(result) | |||
|
204 | try: | |||
|
205 | return str(out) | |||
|
206 | except UnicodeError: | |||
|
207 | return out.encode(self.codec,self.encoding_errors) | |||
|
208 | ||||
|
209 | def __str__(self): | |||
|
210 | """Evaluate and substitute the appropriate parts of the string.""" | |||
|
211 | ||||
|
212 | # We need to skip enough frames to get to the actual caller outside of | |||
|
213 | # Itpl. | |||
|
214 | frame = sys._getframe(1) | |||
|
215 | while frame.f_globals["__name__"] == __name__: frame = frame.f_back | |||
|
216 | loc, glob = frame.f_locals, frame.f_globals | |||
|
217 | ||||
|
218 | return self._str(glob,loc) | |||
|
219 | ||||
|
220 | class ItplNS(Itpl): | |||
|
221 | """Class representing a string with interpolation abilities. | |||
|
222 | ||||
|
223 | This inherits from Itpl, but at creation time a namespace is provided | |||
|
224 | where the evaluation will occur. The interpolation becomes a bit more | |||
|
225 | efficient, as no traceback needs to be extracte. It also allows the | |||
|
226 | caller to supply a different namespace for the interpolation to occur than | |||
|
227 | its own.""" | |||
|
228 | ||||
|
229 | def __init__(self, format,globals,locals=None, | |||
|
230 | codec='utf_8',encoding_errors='backslashreplace'): | |||
|
231 | """ItplNS(format,globals[,locals]) -> interpolating string instance. | |||
|
232 | ||||
|
233 | This constructor, besides a format string, takes a globals dictionary | |||
|
234 | and optionally a locals (which defaults to globals if not provided). | |||
|
235 | ||||
|
236 | For further details, see the Itpl constructor.""" | |||
|
237 | ||||
|
238 | if locals is None: | |||
|
239 | locals = globals | |||
|
240 | self.globals = globals | |||
|
241 | self.locals = locals | |||
|
242 | Itpl.__init__(self,format,codec,encoding_errors) | |||
|
243 | ||||
|
244 | def __str__(self): | |||
|
245 | """Evaluate and substitute the appropriate parts of the string.""" | |||
|
246 | return self._str(self.globals,self.locals) | |||
|
247 | ||||
|
248 | def __repr__(self): | |||
|
249 | return "<ItplNS %s >" % repr(self.format) | |||
|
250 | ||||
|
251 | # utilities for fast printing | |||
|
252 | def itpl(text): return str(Itpl(text)) | |||
|
253 | def printpl(text): print itpl(text) | |||
|
254 | # versions with namespace | |||
|
255 | def itplns(text,globals,locals=None): return str(ItplNS(text,globals,locals)) | |||
|
256 | def printplns(text,globals,locals=None): print itplns(text,globals,locals) | |||
|
257 | ||||
|
258 | class ItplFile: | |||
|
259 | """A file object that filters each write() through an interpolator.""" | |||
|
260 | def __init__(self, file): self.file = file | |||
|
261 | def __repr__(self): return "<interpolated " + repr(self.file) + ">" | |||
|
262 | def __getattr__(self, attr): return getattr(self.file, attr) | |||
|
263 | def write(self, text): self.file.write(str(Itpl(text))) | |||
|
264 | ||||
|
265 | def filter(file=sys.stdout): | |||
|
266 | """Return an ItplFile that filters writes to the given file object. | |||
|
267 | ||||
|
268 | 'file = filter(file)' replaces 'file' with a filtered object that | |||
|
269 | has a write() method. When called with no argument, this creates | |||
|
270 | a filter to sys.stdout.""" | |||
|
271 | return ItplFile(file) | |||
|
272 | ||||
|
273 | def unfilter(ifile=None): | |||
|
274 | """Return the original file that corresponds to the given ItplFile. | |||
|
275 | ||||
|
276 | 'file = unfilter(file)' undoes the effect of 'file = filter(file)'. | |||
|
277 | 'sys.stdout = unfilter()' undoes the effect of 'sys.stdout = filter()'.""" | |||
|
278 | return ifile and ifile.file or sys.stdout.file |
This diff has been collapsed as it changes many lines, (700 lines changed) Show them Hide them | |||||
@@ -0,0 +1,700 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.Async 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide("MochiKit.Async"); | |||
|
13 | dojo.require("MochiKit.Base"); | |||
|
14 | } | |||
|
15 | if (typeof(JSAN) != 'undefined') { | |||
|
16 | JSAN.use("MochiKit.Base", []); | |||
|
17 | } | |||
|
18 | ||||
|
19 | try { | |||
|
20 | if (typeof(MochiKit.Base) == 'undefined') { | |||
|
21 | throw ""; | |||
|
22 | } | |||
|
23 | } catch (e) { | |||
|
24 | throw "MochiKit.Async depends on MochiKit.Base!"; | |||
|
25 | } | |||
|
26 | ||||
|
27 | if (typeof(MochiKit.Async) == 'undefined') { | |||
|
28 | MochiKit.Async = {}; | |||
|
29 | } | |||
|
30 | ||||
|
31 | MochiKit.Async.NAME = "MochiKit.Async"; | |||
|
32 | MochiKit.Async.VERSION = "1.4"; | |||
|
33 | MochiKit.Async.__repr__ = function () { | |||
|
34 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
35 | }; | |||
|
36 | MochiKit.Async.toString = function () { | |||
|
37 | return this.__repr__(); | |||
|
38 | }; | |||
|
39 | ||||
|
40 | /** @id MochiKit.Async.Deferred */ | |||
|
41 | MochiKit.Async.Deferred = function (/* optional */ canceller) { | |||
|
42 | this.chain = []; | |||
|
43 | this.id = this._nextId(); | |||
|
44 | this.fired = -1; | |||
|
45 | this.paused = 0; | |||
|
46 | this.results = [null, null]; | |||
|
47 | this.canceller = canceller; | |||
|
48 | this.silentlyCancelled = false; | |||
|
49 | this.chained = false; | |||
|
50 | }; | |||
|
51 | ||||
|
52 | MochiKit.Async.Deferred.prototype = { | |||
|
53 | /** @id MochiKit.Async.Deferred.prototype.repr */ | |||
|
54 | repr: function () { | |||
|
55 | var state; | |||
|
56 | if (this.fired == -1) { | |||
|
57 | state = 'unfired'; | |||
|
58 | } else if (this.fired === 0) { | |||
|
59 | state = 'success'; | |||
|
60 | } else { | |||
|
61 | state = 'error'; | |||
|
62 | } | |||
|
63 | return 'Deferred(' + this.id + ', ' + state + ')'; | |||
|
64 | }, | |||
|
65 | ||||
|
66 | toString: MochiKit.Base.forwardCall("repr"), | |||
|
67 | ||||
|
68 | _nextId: MochiKit.Base.counter(), | |||
|
69 | ||||
|
70 | /** @id MochiKit.Async.Deferred.prototype.cancel */ | |||
|
71 | cancel: function () { | |||
|
72 | var self = MochiKit.Async; | |||
|
73 | if (this.fired == -1) { | |||
|
74 | if (this.canceller) { | |||
|
75 | this.canceller(this); | |||
|
76 | } else { | |||
|
77 | this.silentlyCancelled = true; | |||
|
78 | } | |||
|
79 | if (this.fired == -1) { | |||
|
80 | this.errback(new self.CancelledError(this)); | |||
|
81 | } | |||
|
82 | } else if ((this.fired === 0) && (this.results[0] instanceof self.Deferred)) { | |||
|
83 | this.results[0].cancel(); | |||
|
84 | } | |||
|
85 | }, | |||
|
86 | ||||
|
87 | _resback: function (res) { | |||
|
88 | /*** | |||
|
89 | ||||
|
90 | The primitive that means either callback or errback | |||
|
91 | ||||
|
92 | ***/ | |||
|
93 | this.fired = ((res instanceof Error) ? 1 : 0); | |||
|
94 | this.results[this.fired] = res; | |||
|
95 | this._fire(); | |||
|
96 | }, | |||
|
97 | ||||
|
98 | _check: function () { | |||
|
99 | if (this.fired != -1) { | |||
|
100 | if (!this.silentlyCancelled) { | |||
|
101 | throw new MochiKit.Async.AlreadyCalledError(this); | |||
|
102 | } | |||
|
103 | this.silentlyCancelled = false; | |||
|
104 | return; | |||
|
105 | } | |||
|
106 | }, | |||
|
107 | ||||
|
108 | /** @id MochiKit.Async.Deferred.prototype.callback */ | |||
|
109 | callback: function (res) { | |||
|
110 | this._check(); | |||
|
111 | if (res instanceof MochiKit.Async.Deferred) { | |||
|
112 | throw new Error("Deferred instances can only be chained if they are the result of a callback"); | |||
|
113 | } | |||
|
114 | this._resback(res); | |||
|
115 | }, | |||
|
116 | ||||
|
117 | /** @id MochiKit.Async.Deferred.prototype.errback */ | |||
|
118 | errback: function (res) { | |||
|
119 | this._check(); | |||
|
120 | var self = MochiKit.Async; | |||
|
121 | if (res instanceof self.Deferred) { | |||
|
122 | throw new Error("Deferred instances can only be chained if they are the result of a callback"); | |||
|
123 | } | |||
|
124 | if (!(res instanceof Error)) { | |||
|
125 | res = new self.GenericError(res); | |||
|
126 | } | |||
|
127 | this._resback(res); | |||
|
128 | }, | |||
|
129 | ||||
|
130 | /** @id MochiKit.Async.Deferred.prototype.addBoth */ | |||
|
131 | addBoth: function (fn) { | |||
|
132 | if (arguments.length > 1) { | |||
|
133 | fn = MochiKit.Base.partial.apply(null, arguments); | |||
|
134 | } | |||
|
135 | return this.addCallbacks(fn, fn); | |||
|
136 | }, | |||
|
137 | ||||
|
138 | /** @id MochiKit.Async.Deferred.prototype.addCallback */ | |||
|
139 | addCallback: function (fn) { | |||
|
140 | if (arguments.length > 1) { | |||
|
141 | fn = MochiKit.Base.partial.apply(null, arguments); | |||
|
142 | } | |||
|
143 | return this.addCallbacks(fn, null); | |||
|
144 | }, | |||
|
145 | ||||
|
146 | /** @id MochiKit.Async.Deferred.prototype.addErrback */ | |||
|
147 | addErrback: function (fn) { | |||
|
148 | if (arguments.length > 1) { | |||
|
149 | fn = MochiKit.Base.partial.apply(null, arguments); | |||
|
150 | } | |||
|
151 | return this.addCallbacks(null, fn); | |||
|
152 | }, | |||
|
153 | ||||
|
154 | /** @id MochiKit.Async.Deferred.prototype.addCallbacks */ | |||
|
155 | addCallbacks: function (cb, eb) { | |||
|
156 | if (this.chained) { | |||
|
157 | throw new Error("Chained Deferreds can not be re-used"); | |||
|
158 | } | |||
|
159 | this.chain.push([cb, eb]); | |||
|
160 | if (this.fired >= 0) { | |||
|
161 | this._fire(); | |||
|
162 | } | |||
|
163 | return this; | |||
|
164 | }, | |||
|
165 | ||||
|
166 | _fire: function () { | |||
|
167 | /*** | |||
|
168 | ||||
|
169 | Used internally to exhaust the callback sequence when a result | |||
|
170 | is available. | |||
|
171 | ||||
|
172 | ***/ | |||
|
173 | var chain = this.chain; | |||
|
174 | var fired = this.fired; | |||
|
175 | var res = this.results[fired]; | |||
|
176 | var self = this; | |||
|
177 | var cb = null; | |||
|
178 | while (chain.length > 0 && this.paused === 0) { | |||
|
179 | // Array | |||
|
180 | var pair = chain.shift(); | |||
|
181 | var f = pair[fired]; | |||
|
182 | if (f === null) { | |||
|
183 | continue; | |||
|
184 | } | |||
|
185 | try { | |||
|
186 | res = f(res); | |||
|
187 | fired = ((res instanceof Error) ? 1 : 0); | |||
|
188 | if (res instanceof MochiKit.Async.Deferred) { | |||
|
189 | cb = function (res) { | |||
|
190 | self._resback(res); | |||
|
191 | self.paused--; | |||
|
192 | if ((self.paused === 0) && (self.fired >= 0)) { | |||
|
193 | self._fire(); | |||
|
194 | } | |||
|
195 | }; | |||
|
196 | this.paused++; | |||
|
197 | } | |||
|
198 | } catch (err) { | |||
|
199 | fired = 1; | |||
|
200 | if (!(err instanceof Error)) { | |||
|
201 | err = new MochiKit.Async.GenericError(err); | |||
|
202 | } | |||
|
203 | res = err; | |||
|
204 | } | |||
|
205 | } | |||
|
206 | this.fired = fired; | |||
|
207 | this.results[fired] = res; | |||
|
208 | if (cb && this.paused) { | |||
|
209 | // this is for "tail recursion" in case the dependent deferred | |||
|
210 | // is already fired | |||
|
211 | res.addBoth(cb); | |||
|
212 | res.chained = true; | |||
|
213 | } | |||
|
214 | } | |||
|
215 | }; | |||
|
216 | ||||
|
217 | MochiKit.Base.update(MochiKit.Async, { | |||
|
218 | /** @id MochiKit.Async.evalJSONRequest */ | |||
|
219 | evalJSONRequest: function (req) { | |||
|
220 | return MochiKit.Base.evalJSON(req.responseText); | |||
|
221 | }, | |||
|
222 | ||||
|
223 | /** @id MochiKit.Async.succeed */ | |||
|
224 | succeed: function (/* optional */result) { | |||
|
225 | var d = new MochiKit.Async.Deferred(); | |||
|
226 | d.callback.apply(d, arguments); | |||
|
227 | return d; | |||
|
228 | }, | |||
|
229 | ||||
|
230 | /** @id MochiKit.Async.fail */ | |||
|
231 | fail: function (/* optional */result) { | |||
|
232 | var d = new MochiKit.Async.Deferred(); | |||
|
233 | d.errback.apply(d, arguments); | |||
|
234 | return d; | |||
|
235 | }, | |||
|
236 | ||||
|
237 | /** @id MochiKit.Async.getXMLHttpRequest */ | |||
|
238 | getXMLHttpRequest: function () { | |||
|
239 | var self = arguments.callee; | |||
|
240 | if (!self.XMLHttpRequest) { | |||
|
241 | var tryThese = [ | |||
|
242 | function () { return new XMLHttpRequest(); }, | |||
|
243 | function () { return new ActiveXObject('Msxml2.XMLHTTP'); }, | |||
|
244 | function () { return new ActiveXObject('Microsoft.XMLHTTP'); }, | |||
|
245 | function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); }, | |||
|
246 | function () { | |||
|
247 | throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest"); | |||
|
248 | } | |||
|
249 | ]; | |||
|
250 | for (var i = 0; i < tryThese.length; i++) { | |||
|
251 | var func = tryThese[i]; | |||
|
252 | try { | |||
|
253 | self.XMLHttpRequest = func; | |||
|
254 | return func(); | |||
|
255 | } catch (e) { | |||
|
256 | // pass | |||
|
257 | } | |||
|
258 | } | |||
|
259 | } | |||
|
260 | return self.XMLHttpRequest(); | |||
|
261 | }, | |||
|
262 | ||||
|
263 | _xhr_onreadystatechange: function (d) { | |||
|
264 | // MochiKit.Logging.logDebug('this.readyState', this.readyState); | |||
|
265 | var m = MochiKit.Base; | |||
|
266 | if (this.readyState == 4) { | |||
|
267 | // IE SUCKS | |||
|
268 | try { | |||
|
269 | this.onreadystatechange = null; | |||
|
270 | } catch (e) { | |||
|
271 | try { | |||
|
272 | this.onreadystatechange = m.noop; | |||
|
273 | } catch (e) { | |||
|
274 | } | |||
|
275 | } | |||
|
276 | var status = null; | |||
|
277 | try { | |||
|
278 | status = this.status; | |||
|
279 | if (!status && m.isNotEmpty(this.responseText)) { | |||
|
280 | // 0 or undefined seems to mean cached or local | |||
|
281 | status = 304; | |||
|
282 | } | |||
|
283 | } catch (e) { | |||
|
284 | // pass | |||
|
285 | // MochiKit.Logging.logDebug('error getting status?', repr(items(e))); | |||
|
286 | } | |||
|
287 | // 200 is OK, 201 is CREATED, 204 is NO CONTENT | |||
|
288 | // 304 is NOT MODIFIED, 1223 is apparently a bug in IE | |||
|
289 | if (status == 200 || status == 201 || status == 204 || | |||
|
290 | status == 304 || status == 1223) { | |||
|
291 | d.callback(this); | |||
|
292 | } else { | |||
|
293 | var err = new MochiKit.Async.XMLHttpRequestError(this, "Request failed"); | |||
|
294 | if (err.number) { | |||
|
295 | // XXX: This seems to happen on page change | |||
|
296 | d.errback(err); | |||
|
297 | } else { | |||
|
298 | // XXX: this seems to happen when the server is unreachable | |||
|
299 | d.errback(err); | |||
|
300 | } | |||
|
301 | } | |||
|
302 | } | |||
|
303 | }, | |||
|
304 | ||||
|
305 | _xhr_canceller: function (req) { | |||
|
306 | // IE SUCKS | |||
|
307 | try { | |||
|
308 | req.onreadystatechange = null; | |||
|
309 | } catch (e) { | |||
|
310 | try { | |||
|
311 | req.onreadystatechange = MochiKit.Base.noop; | |||
|
312 | } catch (e) { | |||
|
313 | } | |||
|
314 | } | |||
|
315 | req.abort(); | |||
|
316 | }, | |||
|
317 | ||||
|
318 | ||||
|
319 | /** @id MochiKit.Async.sendXMLHttpRequest */ | |||
|
320 | sendXMLHttpRequest: function (req, /* optional */ sendContent) { | |||
|
321 | if (typeof(sendContent) == "undefined" || sendContent === null) { | |||
|
322 | sendContent = ""; | |||
|
323 | } | |||
|
324 | ||||
|
325 | var m = MochiKit.Base; | |||
|
326 | var self = MochiKit.Async; | |||
|
327 | var d = new self.Deferred(m.partial(self._xhr_canceller, req)); | |||
|
328 | ||||
|
329 | try { | |||
|
330 | req.onreadystatechange = m.bind(self._xhr_onreadystatechange, | |||
|
331 | req, d); | |||
|
332 | req.send(sendContent); | |||
|
333 | } catch (e) { | |||
|
334 | try { | |||
|
335 | req.onreadystatechange = null; | |||
|
336 | } catch (ignore) { | |||
|
337 | // pass | |||
|
338 | } | |||
|
339 | d.errback(e); | |||
|
340 | } | |||
|
341 | ||||
|
342 | return d; | |||
|
343 | ||||
|
344 | }, | |||
|
345 | ||||
|
346 | /** @id MochiKit.Async.doXHR */ | |||
|
347 | doXHR: function (url, opts) { | |||
|
348 | /* | |||
|
349 | Work around a Firefox bug by dealing with XHR during | |||
|
350 | the next event loop iteration. Maybe it's this one: | |||
|
351 | https://bugzilla.mozilla.org/show_bug.cgi?id=249843 | |||
|
352 | */ | |||
|
353 | var self = MochiKit.Async; | |||
|
354 | return self.callLater(0, self._doXHR, url, opts); | |||
|
355 | }, | |||
|
356 | ||||
|
357 | _doXHR: function (url, opts) { | |||
|
358 | var m = MochiKit.Base; | |||
|
359 | opts = m.update({ | |||
|
360 | method: 'GET', | |||
|
361 | sendContent: '' | |||
|
362 | /* | |||
|
363 | queryString: undefined, | |||
|
364 | username: undefined, | |||
|
365 | password: undefined, | |||
|
366 | headers: undefined, | |||
|
367 | mimeType: undefined | |||
|
368 | */ | |||
|
369 | }, opts); | |||
|
370 | var self = MochiKit.Async; | |||
|
371 | var req = self.getXMLHttpRequest(); | |||
|
372 | if (opts.queryString) { | |||
|
373 | var qs = m.queryString(opts.queryString); | |||
|
374 | if (qs) { | |||
|
375 | url += "?" + qs; | |||
|
376 | } | |||
|
377 | } | |||
|
378 | // Safari will send undefined:undefined, so we have to check. | |||
|
379 | // We can't use apply, since the function is native. | |||
|
380 | if ('username' in opts) { | |||
|
381 | req.open(opts.method, url, true, opts.username, opts.password); | |||
|
382 | } else { | |||
|
383 | req.open(opts.method, url, true); | |||
|
384 | } | |||
|
385 | if (req.overrideMimeType && opts.mimeType) { | |||
|
386 | req.overrideMimeType(opts.mimeType); | |||
|
387 | } | |||
|
388 | req.setRequestHeader("X-Requested-With", "XMLHttpRequest"); | |||
|
389 | if (opts.headers) { | |||
|
390 | var headers = opts.headers; | |||
|
391 | if (!m.isArrayLike(headers)) { | |||
|
392 | headers = m.items(headers); | |||
|
393 | } | |||
|
394 | for (var i = 0; i < headers.length; i++) { | |||
|
395 | var header = headers[i]; | |||
|
396 | var name = header[0]; | |||
|
397 | var value = header[1]; | |||
|
398 | req.setRequestHeader(name, value); | |||
|
399 | } | |||
|
400 | } | |||
|
401 | return self.sendXMLHttpRequest(req, opts.sendContent); | |||
|
402 | }, | |||
|
403 | ||||
|
404 | _buildURL: function (url/*, ...*/) { | |||
|
405 | if (arguments.length > 1) { | |||
|
406 | var m = MochiKit.Base; | |||
|
407 | var qs = m.queryString.apply(null, m.extend(null, arguments, 1)); | |||
|
408 | if (qs) { | |||
|
409 | return url + "?" + qs; | |||
|
410 | } | |||
|
411 | } | |||
|
412 | return url; | |||
|
413 | }, | |||
|
414 | ||||
|
415 | /** @id MochiKit.Async.doSimpleXMLHttpRequest */ | |||
|
416 | doSimpleXMLHttpRequest: function (url/*, ...*/) { | |||
|
417 | var self = MochiKit.Async; | |||
|
418 | url = self._buildURL.apply(self, arguments); | |||
|
419 | return self.doXHR(url); | |||
|
420 | }, | |||
|
421 | ||||
|
422 | /** @id MochiKit.Async.loadJSONDoc */ | |||
|
423 | loadJSONDoc: function (url/*, ...*/) { | |||
|
424 | var self = MochiKit.Async; | |||
|
425 | url = self._buildURL.apply(self, arguments); | |||
|
426 | var d = self.doXHR(url, { | |||
|
427 | 'mimeType': 'text/plain', | |||
|
428 | 'headers': [['Accept', 'application/json']] | |||
|
429 | }); | |||
|
430 | d = d.addCallback(self.evalJSONRequest); | |||
|
431 | return d; | |||
|
432 | }, | |||
|
433 | ||||
|
434 | /** @id MochiKit.Async.wait */ | |||
|
435 | wait: function (seconds, /* optional */value) { | |||
|
436 | var d = new MochiKit.Async.Deferred(); | |||
|
437 | var m = MochiKit.Base; | |||
|
438 | if (typeof(value) != 'undefined') { | |||
|
439 | d.addCallback(function () { return value; }); | |||
|
440 | } | |||
|
441 | var timeout = setTimeout( | |||
|
442 | m.bind("callback", d), | |||
|
443 | Math.floor(seconds * 1000)); | |||
|
444 | d.canceller = function () { | |||
|
445 | try { | |||
|
446 | clearTimeout(timeout); | |||
|
447 | } catch (e) { | |||
|
448 | // pass | |||
|
449 | } | |||
|
450 | }; | |||
|
451 | return d; | |||
|
452 | }, | |||
|
453 | ||||
|
454 | /** @id MochiKit.Async.callLater */ | |||
|
455 | callLater: function (seconds, func) { | |||
|
456 | var m = MochiKit.Base; | |||
|
457 | var pfunc = m.partial.apply(m, m.extend(null, arguments, 1)); | |||
|
458 | return MochiKit.Async.wait(seconds).addCallback( | |||
|
459 | function (res) { return pfunc(); } | |||
|
460 | ); | |||
|
461 | } | |||
|
462 | }); | |||
|
463 | ||||
|
464 | ||||
|
465 | /** @id MochiKit.Async.DeferredLock */ | |||
|
466 | MochiKit.Async.DeferredLock = function () { | |||
|
467 | this.waiting = []; | |||
|
468 | this.locked = false; | |||
|
469 | this.id = this._nextId(); | |||
|
470 | }; | |||
|
471 | ||||
|
472 | MochiKit.Async.DeferredLock.prototype = { | |||
|
473 | __class__: MochiKit.Async.DeferredLock, | |||
|
474 | /** @id MochiKit.Async.DeferredLock.prototype.acquire */ | |||
|
475 | acquire: function () { | |||
|
476 | var d = new MochiKit.Async.Deferred(); | |||
|
477 | if (this.locked) { | |||
|
478 | this.waiting.push(d); | |||
|
479 | } else { | |||
|
480 | this.locked = true; | |||
|
481 | d.callback(this); | |||
|
482 | } | |||
|
483 | return d; | |||
|
484 | }, | |||
|
485 | /** @id MochiKit.Async.DeferredLock.prototype.release */ | |||
|
486 | release: function () { | |||
|
487 | if (!this.locked) { | |||
|
488 | throw TypeError("Tried to release an unlocked DeferredLock"); | |||
|
489 | } | |||
|
490 | this.locked = false; | |||
|
491 | if (this.waiting.length > 0) { | |||
|
492 | this.locked = true; | |||
|
493 | this.waiting.shift().callback(this); | |||
|
494 | } | |||
|
495 | }, | |||
|
496 | _nextId: MochiKit.Base.counter(), | |||
|
497 | repr: function () { | |||
|
498 | var state; | |||
|
499 | if (this.locked) { | |||
|
500 | state = 'locked, ' + this.waiting.length + ' waiting'; | |||
|
501 | } else { | |||
|
502 | state = 'unlocked'; | |||
|
503 | } | |||
|
504 | return 'DeferredLock(' + this.id + ', ' + state + ')'; | |||
|
505 | }, | |||
|
506 | toString: MochiKit.Base.forwardCall("repr") | |||
|
507 | ||||
|
508 | }; | |||
|
509 | ||||
|
510 | /** @id MochiKit.Async.DeferredList */ | |||
|
511 | MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) { | |||
|
512 | ||||
|
513 | // call parent constructor | |||
|
514 | MochiKit.Async.Deferred.apply(this, [canceller]); | |||
|
515 | ||||
|
516 | this.list = list; | |||
|
517 | var resultList = []; | |||
|
518 | this.resultList = resultList; | |||
|
519 | ||||
|
520 | this.finishedCount = 0; | |||
|
521 | this.fireOnOneCallback = fireOnOneCallback; | |||
|
522 | this.fireOnOneErrback = fireOnOneErrback; | |||
|
523 | this.consumeErrors = consumeErrors; | |||
|
524 | ||||
|
525 | var cb = MochiKit.Base.bind(this._cbDeferred, this); | |||
|
526 | for (var i = 0; i < list.length; i++) { | |||
|
527 | var d = list[i]; | |||
|
528 | resultList.push(undefined); | |||
|
529 | d.addCallback(cb, i, true); | |||
|
530 | d.addErrback(cb, i, false); | |||
|
531 | } | |||
|
532 | ||||
|
533 | if (list.length === 0 && !fireOnOneCallback) { | |||
|
534 | this.callback(this.resultList); | |||
|
535 | } | |||
|
536 | ||||
|
537 | }; | |||
|
538 | ||||
|
539 | MochiKit.Async.DeferredList.prototype = new MochiKit.Async.Deferred(); | |||
|
540 | ||||
|
541 | MochiKit.Async.DeferredList.prototype._cbDeferred = function (index, succeeded, result) { | |||
|
542 | this.resultList[index] = [succeeded, result]; | |||
|
543 | this.finishedCount += 1; | |||
|
544 | if (this.fired == -1) { | |||
|
545 | if (succeeded && this.fireOnOneCallback) { | |||
|
546 | this.callback([index, result]); | |||
|
547 | } else if (!succeeded && this.fireOnOneErrback) { | |||
|
548 | this.errback(result); | |||
|
549 | } else if (this.finishedCount == this.list.length) { | |||
|
550 | this.callback(this.resultList); | |||
|
551 | } | |||
|
552 | } | |||
|
553 | if (!succeeded && this.consumeErrors) { | |||
|
554 | result = null; | |||
|
555 | } | |||
|
556 | return result; | |||
|
557 | }; | |||
|
558 | ||||
|
559 | /** @id MochiKit.Async.gatherResults */ | |||
|
560 | MochiKit.Async.gatherResults = function (deferredList) { | |||
|
561 | var d = new MochiKit.Async.DeferredList(deferredList, false, true, false); | |||
|
562 | d.addCallback(function (results) { | |||
|
563 | var ret = []; | |||
|
564 | for (var i = 0; i < results.length; i++) { | |||
|
565 | ret.push(results[i][1]); | |||
|
566 | } | |||
|
567 | return ret; | |||
|
568 | }); | |||
|
569 | return d; | |||
|
570 | }; | |||
|
571 | ||||
|
572 | /** @id MochiKit.Async.maybeDeferred */ | |||
|
573 | MochiKit.Async.maybeDeferred = function (func) { | |||
|
574 | var self = MochiKit.Async; | |||
|
575 | var result; | |||
|
576 | try { | |||
|
577 | var r = func.apply(null, MochiKit.Base.extend([], arguments, 1)); | |||
|
578 | if (r instanceof self.Deferred) { | |||
|
579 | result = r; | |||
|
580 | } else if (r instanceof Error) { | |||
|
581 | result = self.fail(r); | |||
|
582 | } else { | |||
|
583 | result = self.succeed(r); | |||
|
584 | } | |||
|
585 | } catch (e) { | |||
|
586 | result = self.fail(e); | |||
|
587 | } | |||
|
588 | return result; | |||
|
589 | }; | |||
|
590 | ||||
|
591 | ||||
|
592 | MochiKit.Async.EXPORT = [ | |||
|
593 | "AlreadyCalledError", | |||
|
594 | "CancelledError", | |||
|
595 | "BrowserComplianceError", | |||
|
596 | "GenericError", | |||
|
597 | "XMLHttpRequestError", | |||
|
598 | "Deferred", | |||
|
599 | "succeed", | |||
|
600 | "fail", | |||
|
601 | "getXMLHttpRequest", | |||
|
602 | "doSimpleXMLHttpRequest", | |||
|
603 | "loadJSONDoc", | |||
|
604 | "wait", | |||
|
605 | "callLater", | |||
|
606 | "sendXMLHttpRequest", | |||
|
607 | "DeferredLock", | |||
|
608 | "DeferredList", | |||
|
609 | "gatherResults", | |||
|
610 | "maybeDeferred", | |||
|
611 | "doXHR" | |||
|
612 | ]; | |||
|
613 | ||||
|
614 | MochiKit.Async.EXPORT_OK = [ | |||
|
615 | "evalJSONRequest" | |||
|
616 | ]; | |||
|
617 | ||||
|
618 | MochiKit.Async.__new__ = function () { | |||
|
619 | var m = MochiKit.Base; | |||
|
620 | var ne = m.partial(m._newNamedError, this); | |||
|
621 | ||||
|
622 | ne("AlreadyCalledError", | |||
|
623 | /** @id MochiKit.Async.AlreadyCalledError */ | |||
|
624 | function (deferred) { | |||
|
625 | /*** | |||
|
626 | ||||
|
627 | Raised by the Deferred if callback or errback happens | |||
|
628 | after it was already fired. | |||
|
629 | ||||
|
630 | ***/ | |||
|
631 | this.deferred = deferred; | |||
|
632 | } | |||
|
633 | ); | |||
|
634 | ||||
|
635 | ne("CancelledError", | |||
|
636 | /** @id MochiKit.Async.CancelledError */ | |||
|
637 | function (deferred) { | |||
|
638 | /*** | |||
|
639 | ||||
|
640 | Raised by the Deferred cancellation mechanism. | |||
|
641 | ||||
|
642 | ***/ | |||
|
643 | this.deferred = deferred; | |||
|
644 | } | |||
|
645 | ); | |||
|
646 | ||||
|
647 | ne("BrowserComplianceError", | |||
|
648 | /** @id MochiKit.Async.BrowserComplianceError */ | |||
|
649 | function (msg) { | |||
|
650 | /*** | |||
|
651 | ||||
|
652 | Raised when the JavaScript runtime is not capable of performing | |||
|
653 | the given function. Technically, this should really never be | |||
|
654 | raised because a non-conforming JavaScript runtime probably | |||
|
655 | isn't going to support exceptions in the first place. | |||
|
656 | ||||
|
657 | ***/ | |||
|
658 | this.message = msg; | |||
|
659 | } | |||
|
660 | ); | |||
|
661 | ||||
|
662 | ne("GenericError", | |||
|
663 | /** @id MochiKit.Async.GenericError */ | |||
|
664 | function (msg) { | |||
|
665 | this.message = msg; | |||
|
666 | } | |||
|
667 | ); | |||
|
668 | ||||
|
669 | ne("XMLHttpRequestError", | |||
|
670 | /** @id MochiKit.Async.XMLHttpRequestError */ | |||
|
671 | function (req, msg) { | |||
|
672 | /*** | |||
|
673 | ||||
|
674 | Raised when an XMLHttpRequest does not complete for any reason. | |||
|
675 | ||||
|
676 | ***/ | |||
|
677 | this.req = req; | |||
|
678 | this.message = msg; | |||
|
679 | try { | |||
|
680 | // Strange but true that this can raise in some cases. | |||
|
681 | this.number = req.status; | |||
|
682 | } catch (e) { | |||
|
683 | // pass | |||
|
684 | } | |||
|
685 | } | |||
|
686 | ); | |||
|
687 | ||||
|
688 | ||||
|
689 | this.EXPORT_TAGS = { | |||
|
690 | ":common": this.EXPORT, | |||
|
691 | ":all": m.concat(this.EXPORT, this.EXPORT_OK) | |||
|
692 | }; | |||
|
693 | ||||
|
694 | m.nameFunctions(this); | |||
|
695 | ||||
|
696 | }; | |||
|
697 | ||||
|
698 | MochiKit.Async.__new__(); | |||
|
699 | ||||
|
700 | MochiKit.Base._exportSymbols(this, MochiKit.Async); |
This diff has been collapsed as it changes many lines, (1413 lines changed) Show them Hide them | |||||
@@ -0,0 +1,1413 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.Base 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide("MochiKit.Base"); | |||
|
13 | } | |||
|
14 | if (typeof(MochiKit) == 'undefined') { | |||
|
15 | MochiKit = {}; | |||
|
16 | } | |||
|
17 | if (typeof(MochiKit.Base) == 'undefined') { | |||
|
18 | MochiKit.Base = {}; | |||
|
19 | } | |||
|
20 | if (typeof(MochiKit.__export__) == "undefined") { | |||
|
21 | MochiKit.__export__ = (MochiKit.__compat__ || | |||
|
22 | (typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined') | |||
|
23 | ); | |||
|
24 | } | |||
|
25 | ||||
|
26 | MochiKit.Base.VERSION = "1.4"; | |||
|
27 | MochiKit.Base.NAME = "MochiKit.Base"; | |||
|
28 | /** @id MochiKit.Base.update */ | |||
|
29 | MochiKit.Base.update = function (self, obj/*, ... */) { | |||
|
30 | if (self === null || self === undefined) { | |||
|
31 | self = {}; | |||
|
32 | } | |||
|
33 | for (var i = 1; i < arguments.length; i++) { | |||
|
34 | var o = arguments[i]; | |||
|
35 | if (typeof(o) != 'undefined' && o !== null) { | |||
|
36 | for (var k in o) { | |||
|
37 | self[k] = o[k]; | |||
|
38 | } | |||
|
39 | } | |||
|
40 | } | |||
|
41 | return self; | |||
|
42 | }; | |||
|
43 | ||||
|
44 | MochiKit.Base.update(MochiKit.Base, { | |||
|
45 | __repr__: function () { | |||
|
46 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
47 | }, | |||
|
48 | ||||
|
49 | toString: function () { | |||
|
50 | return this.__repr__(); | |||
|
51 | }, | |||
|
52 | ||||
|
53 | /** @id MochiKit.Base.camelize */ | |||
|
54 | camelize: function (selector) { | |||
|
55 | /* from dojo.style.toCamelCase */ | |||
|
56 | var arr = selector.split('-'); | |||
|
57 | var cc = arr[0]; | |||
|
58 | for (var i = 1; i < arr.length; i++) { | |||
|
59 | cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1); | |||
|
60 | } | |||
|
61 | return cc; | |||
|
62 | }, | |||
|
63 | ||||
|
64 | /** @id MochiKit.Base.counter */ | |||
|
65 | counter: function (n/* = 1 */) { | |||
|
66 | if (arguments.length === 0) { | |||
|
67 | n = 1; | |||
|
68 | } | |||
|
69 | return function () { | |||
|
70 | return n++; | |||
|
71 | }; | |||
|
72 | }, | |||
|
73 | ||||
|
74 | /** @id MochiKit.Base.clone */ | |||
|
75 | clone: function (obj) { | |||
|
76 | var me = arguments.callee; | |||
|
77 | if (arguments.length == 1) { | |||
|
78 | me.prototype = obj; | |||
|
79 | return new me(); | |||
|
80 | } | |||
|
81 | }, | |||
|
82 | ||||
|
83 | _flattenArray: function (res, lst) { | |||
|
84 | for (var i = 0; i < lst.length; i++) { | |||
|
85 | var o = lst[i]; | |||
|
86 | if (o instanceof Array) { | |||
|
87 | arguments.callee(res, o); | |||
|
88 | } else { | |||
|
89 | res.push(o); | |||
|
90 | } | |||
|
91 | } | |||
|
92 | return res; | |||
|
93 | }, | |||
|
94 | ||||
|
95 | /** @id MochiKit.Base.flattenArray */ | |||
|
96 | flattenArray: function (lst) { | |||
|
97 | return MochiKit.Base._flattenArray([], lst); | |||
|
98 | }, | |||
|
99 | ||||
|
100 | /** @id MochiKit.Base.flattenArguments */ | |||
|
101 | flattenArguments: function (lst/* ...*/) { | |||
|
102 | var res = []; | |||
|
103 | var m = MochiKit.Base; | |||
|
104 | var args = m.extend(null, arguments); | |||
|
105 | while (args.length) { | |||
|
106 | var o = args.shift(); | |||
|
107 | if (o && typeof(o) == "object" && typeof(o.length) == "number") { | |||
|
108 | for (var i = o.length - 1; i >= 0; i--) { | |||
|
109 | args.unshift(o[i]); | |||
|
110 | } | |||
|
111 | } else { | |||
|
112 | res.push(o); | |||
|
113 | } | |||
|
114 | } | |||
|
115 | return res; | |||
|
116 | }, | |||
|
117 | ||||
|
118 | /** @id MochiKit.Base.extend */ | |||
|
119 | extend: function (self, obj, /* optional */skip) { | |||
|
120 | // Extend an array with an array-like object starting | |||
|
121 | // from the skip index | |||
|
122 | if (!skip) { | |||
|
123 | skip = 0; | |||
|
124 | } | |||
|
125 | if (obj) { | |||
|
126 | // allow iterable fall-through, but skip the full isArrayLike | |||
|
127 | // check for speed, this is called often. | |||
|
128 | var l = obj.length; | |||
|
129 | if (typeof(l) != 'number' /* !isArrayLike(obj) */) { | |||
|
130 | if (typeof(MochiKit.Iter) != "undefined") { | |||
|
131 | obj = MochiKit.Iter.list(obj); | |||
|
132 | l = obj.length; | |||
|
133 | } else { | |||
|
134 | throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); | |||
|
135 | } | |||
|
136 | } | |||
|
137 | if (!self) { | |||
|
138 | self = []; | |||
|
139 | } | |||
|
140 | for (var i = skip; i < l; i++) { | |||
|
141 | self.push(obj[i]); | |||
|
142 | } | |||
|
143 | } | |||
|
144 | // This mutates, but it's convenient to return because | |||
|
145 | // it's often used like a constructor when turning some | |||
|
146 | // ghetto array-like to a real array | |||
|
147 | return self; | |||
|
148 | }, | |||
|
149 | ||||
|
150 | ||||
|
151 | /** @id MochiKit.Base.updatetree */ | |||
|
152 | updatetree: function (self, obj/*, ...*/) { | |||
|
153 | if (self === null || self === undefined) { | |||
|
154 | self = {}; | |||
|
155 | } | |||
|
156 | for (var i = 1; i < arguments.length; i++) { | |||
|
157 | var o = arguments[i]; | |||
|
158 | if (typeof(o) != 'undefined' && o !== null) { | |||
|
159 | for (var k in o) { | |||
|
160 | var v = o[k]; | |||
|
161 | if (typeof(self[k]) == 'object' && typeof(v) == 'object') { | |||
|
162 | arguments.callee(self[k], v); | |||
|
163 | } else { | |||
|
164 | self[k] = v; | |||
|
165 | } | |||
|
166 | } | |||
|
167 | } | |||
|
168 | } | |||
|
169 | return self; | |||
|
170 | }, | |||
|
171 | ||||
|
172 | /** @id MochiKit.Base.setdefault */ | |||
|
173 | setdefault: function (self, obj/*, ...*/) { | |||
|
174 | if (self === null || self === undefined) { | |||
|
175 | self = {}; | |||
|
176 | } | |||
|
177 | for (var i = 1; i < arguments.length; i++) { | |||
|
178 | var o = arguments[i]; | |||
|
179 | for (var k in o) { | |||
|
180 | if (!(k in self)) { | |||
|
181 | self[k] = o[k]; | |||
|
182 | } | |||
|
183 | } | |||
|
184 | } | |||
|
185 | return self; | |||
|
186 | }, | |||
|
187 | ||||
|
188 | /** @id MochiKit.Base.keys */ | |||
|
189 | keys: function (obj) { | |||
|
190 | var rval = []; | |||
|
191 | for (var prop in obj) { | |||
|
192 | rval.push(prop); | |||
|
193 | } | |||
|
194 | return rval; | |||
|
195 | }, | |||
|
196 | ||||
|
197 | /** @id MochiKit.Base.values */ | |||
|
198 | values: function (obj) { | |||
|
199 | var rval = []; | |||
|
200 | for (var prop in obj) { | |||
|
201 | rval.push(obj[prop]); | |||
|
202 | } | |||
|
203 | return rval; | |||
|
204 | }, | |||
|
205 | ||||
|
206 | /** @id MochiKit.Base.items */ | |||
|
207 | items: function (obj) { | |||
|
208 | var rval = []; | |||
|
209 | var e; | |||
|
210 | for (var prop in obj) { | |||
|
211 | var v; | |||
|
212 | try { | |||
|
213 | v = obj[prop]; | |||
|
214 | } catch (e) { | |||
|
215 | continue; | |||
|
216 | } | |||
|
217 | rval.push([prop, v]); | |||
|
218 | } | |||
|
219 | return rval; | |||
|
220 | }, | |||
|
221 | ||||
|
222 | ||||
|
223 | _newNamedError: function (module, name, func) { | |||
|
224 | func.prototype = new MochiKit.Base.NamedError(module.NAME + "." + name); | |||
|
225 | module[name] = func; | |||
|
226 | }, | |||
|
227 | ||||
|
228 | ||||
|
229 | /** @id MochiKit.Base.operator */ | |||
|
230 | operator: { | |||
|
231 | // unary logic operators | |||
|
232 | /** @id MochiKit.Base.truth */ | |||
|
233 | truth: function (a) { return !!a; }, | |||
|
234 | /** @id MochiKit.Base.lognot */ | |||
|
235 | lognot: function (a) { return !a; }, | |||
|
236 | /** @id MochiKit.Base.identity */ | |||
|
237 | identity: function (a) { return a; }, | |||
|
238 | ||||
|
239 | // bitwise unary operators | |||
|
240 | /** @id MochiKit.Base.not */ | |||
|
241 | not: function (a) { return ~a; }, | |||
|
242 | /** @id MochiKit.Base.neg */ | |||
|
243 | neg: function (a) { return -a; }, | |||
|
244 | ||||
|
245 | // binary operators | |||
|
246 | /** @id MochiKit.Base.add */ | |||
|
247 | add: function (a, b) { return a + b; }, | |||
|
248 | /** @id MochiKit.Base.sub */ | |||
|
249 | sub: function (a, b) { return a - b; }, | |||
|
250 | /** @id MochiKit.Base.div */ | |||
|
251 | div: function (a, b) { return a / b; }, | |||
|
252 | /** @id MochiKit.Base.mod */ | |||
|
253 | mod: function (a, b) { return a % b; }, | |||
|
254 | /** @id MochiKit.Base.mul */ | |||
|
255 | mul: function (a, b) { return a * b; }, | |||
|
256 | ||||
|
257 | // bitwise binary operators | |||
|
258 | /** @id MochiKit.Base.and */ | |||
|
259 | and: function (a, b) { return a & b; }, | |||
|
260 | /** @id MochiKit.Base.or */ | |||
|
261 | or: function (a, b) { return a | b; }, | |||
|
262 | /** @id MochiKit.Base.xor */ | |||
|
263 | xor: function (a, b) { return a ^ b; }, | |||
|
264 | /** @id MochiKit.Base.lshift */ | |||
|
265 | lshift: function (a, b) { return a << b; }, | |||
|
266 | /** @id MochiKit.Base.rshift */ | |||
|
267 | rshift: function (a, b) { return a >> b; }, | |||
|
268 | /** @id MochiKit.Base.zrshift */ | |||
|
269 | zrshift: function (a, b) { return a >>> b; }, | |||
|
270 | ||||
|
271 | // near-worthless built-in comparators | |||
|
272 | /** @id MochiKit.Base.eq */ | |||
|
273 | eq: function (a, b) { return a == b; }, | |||
|
274 | /** @id MochiKit.Base.ne */ | |||
|
275 | ne: function (a, b) { return a != b; }, | |||
|
276 | /** @id MochiKit.Base.gt */ | |||
|
277 | gt: function (a, b) { return a > b; }, | |||
|
278 | /** @id MochiKit.Base.ge */ | |||
|
279 | ge: function (a, b) { return a >= b; }, | |||
|
280 | /** @id MochiKit.Base.lt */ | |||
|
281 | lt: function (a, b) { return a < b; }, | |||
|
282 | /** @id MochiKit.Base.le */ | |||
|
283 | le: function (a, b) { return a <= b; }, | |||
|
284 | ||||
|
285 | // strict built-in comparators | |||
|
286 | seq: function (a, b) { return a === b; }, | |||
|
287 | sne: function (a, b) { return a !== b; }, | |||
|
288 | ||||
|
289 | // compare comparators | |||
|
290 | /** @id MochiKit.Base.ceq */ | |||
|
291 | ceq: function (a, b) { return MochiKit.Base.compare(a, b) === 0; }, | |||
|
292 | /** @id MochiKit.Base.cne */ | |||
|
293 | cne: function (a, b) { return MochiKit.Base.compare(a, b) !== 0; }, | |||
|
294 | /** @id MochiKit.Base.cgt */ | |||
|
295 | cgt: function (a, b) { return MochiKit.Base.compare(a, b) == 1; }, | |||
|
296 | /** @id MochiKit.Base.cge */ | |||
|
297 | cge: function (a, b) { return MochiKit.Base.compare(a, b) != -1; }, | |||
|
298 | /** @id MochiKit.Base.clt */ | |||
|
299 | clt: function (a, b) { return MochiKit.Base.compare(a, b) == -1; }, | |||
|
300 | /** @id MochiKit.Base.cle */ | |||
|
301 | cle: function (a, b) { return MochiKit.Base.compare(a, b) != 1; }, | |||
|
302 | ||||
|
303 | // binary logical operators | |||
|
304 | /** @id MochiKit.Base.logand */ | |||
|
305 | logand: function (a, b) { return a && b; }, | |||
|
306 | /** @id MochiKit.Base.logor */ | |||
|
307 | logor: function (a, b) { return a || b; }, | |||
|
308 | /** @id MochiKit.Base.contains */ | |||
|
309 | contains: function (a, b) { return b in a; } | |||
|
310 | }, | |||
|
311 | ||||
|
312 | /** @id MochiKit.Base.forwardCall */ | |||
|
313 | forwardCall: function (func) { | |||
|
314 | return function () { | |||
|
315 | return this[func].apply(this, arguments); | |||
|
316 | }; | |||
|
317 | }, | |||
|
318 | ||||
|
319 | /** @id MochiKit.Base.itemgetter */ | |||
|
320 | itemgetter: function (func) { | |||
|
321 | return function (arg) { | |||
|
322 | return arg[func]; | |||
|
323 | }; | |||
|
324 | }, | |||
|
325 | ||||
|
326 | /** @id MochiKit.Base.typeMatcher */ | |||
|
327 | typeMatcher: function (/* typ */) { | |||
|
328 | var types = {}; | |||
|
329 | for (var i = 0; i < arguments.length; i++) { | |||
|
330 | var typ = arguments[i]; | |||
|
331 | types[typ] = typ; | |||
|
332 | } | |||
|
333 | return function () { | |||
|
334 | for (var i = 0; i < arguments.length; i++) { | |||
|
335 | if (!(typeof(arguments[i]) in types)) { | |||
|
336 | return false; | |||
|
337 | } | |||
|
338 | } | |||
|
339 | return true; | |||
|
340 | }; | |||
|
341 | }, | |||
|
342 | ||||
|
343 | /** @id MochiKit.Base.isNull */ | |||
|
344 | isNull: function (/* ... */) { | |||
|
345 | for (var i = 0; i < arguments.length; i++) { | |||
|
346 | if (arguments[i] !== null) { | |||
|
347 | return false; | |||
|
348 | } | |||
|
349 | } | |||
|
350 | return true; | |||
|
351 | }, | |||
|
352 | ||||
|
353 | /** @id MochiKit.Base.isUndefinedOrNull */ | |||
|
354 | isUndefinedOrNull: function (/* ... */) { | |||
|
355 | for (var i = 0; i < arguments.length; i++) { | |||
|
356 | var o = arguments[i]; | |||
|
357 | if (!(typeof(o) == 'undefined' || o === null)) { | |||
|
358 | return false; | |||
|
359 | } | |||
|
360 | } | |||
|
361 | return true; | |||
|
362 | }, | |||
|
363 | ||||
|
364 | /** @id MochiKit.Base.isEmpty */ | |||
|
365 | isEmpty: function (obj) { | |||
|
366 | return !MochiKit.Base.isNotEmpty.apply(this, arguments); | |||
|
367 | }, | |||
|
368 | ||||
|
369 | /** @id MochiKit.Base.isNotEmpty */ | |||
|
370 | isNotEmpty: function (obj) { | |||
|
371 | for (var i = 0; i < arguments.length; i++) { | |||
|
372 | var o = arguments[i]; | |||
|
373 | if (!(o && o.length)) { | |||
|
374 | return false; | |||
|
375 | } | |||
|
376 | } | |||
|
377 | return true; | |||
|
378 | }, | |||
|
379 | ||||
|
380 | /** @id MochiKit.Base.isArrayLike */ | |||
|
381 | isArrayLike: function () { | |||
|
382 | for (var i = 0; i < arguments.length; i++) { | |||
|
383 | var o = arguments[i]; | |||
|
384 | var typ = typeof(o); | |||
|
385 | if ( | |||
|
386 | (typ != 'object' && !(typ == 'function' && typeof(o.item) == 'function')) || | |||
|
387 | o === null || | |||
|
388 | typeof(o.length) != 'number' || | |||
|
389 | o.nodeType === 3 | |||
|
390 | ) { | |||
|
391 | return false; | |||
|
392 | } | |||
|
393 | } | |||
|
394 | return true; | |||
|
395 | }, | |||
|
396 | ||||
|
397 | /** @id MochiKit.Base.isDateLike */ | |||
|
398 | isDateLike: function () { | |||
|
399 | for (var i = 0; i < arguments.length; i++) { | |||
|
400 | var o = arguments[i]; | |||
|
401 | if (typeof(o) != "object" || o === null | |||
|
402 | || typeof(o.getTime) != 'function') { | |||
|
403 | return false; | |||
|
404 | } | |||
|
405 | } | |||
|
406 | return true; | |||
|
407 | }, | |||
|
408 | ||||
|
409 | ||||
|
410 | /** @id MochiKit.Base.xmap */ | |||
|
411 | xmap: function (fn/*, obj... */) { | |||
|
412 | if (fn === null) { | |||
|
413 | return MochiKit.Base.extend(null, arguments, 1); | |||
|
414 | } | |||
|
415 | var rval = []; | |||
|
416 | for (var i = 1; i < arguments.length; i++) { | |||
|
417 | rval.push(fn(arguments[i])); | |||
|
418 | } | |||
|
419 | return rval; | |||
|
420 | }, | |||
|
421 | ||||
|
422 | /** @id MochiKit.Base.map */ | |||
|
423 | map: function (fn, lst/*, lst... */) { | |||
|
424 | var m = MochiKit.Base; | |||
|
425 | var itr = MochiKit.Iter; | |||
|
426 | var isArrayLike = m.isArrayLike; | |||
|
427 | if (arguments.length <= 2) { | |||
|
428 | // allow an iterable to be passed | |||
|
429 | if (!isArrayLike(lst)) { | |||
|
430 | if (itr) { | |||
|
431 | // fast path for map(null, iterable) | |||
|
432 | lst = itr.list(lst); | |||
|
433 | if (fn === null) { | |||
|
434 | return lst; | |||
|
435 | } | |||
|
436 | } else { | |||
|
437 | throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); | |||
|
438 | } | |||
|
439 | } | |||
|
440 | // fast path for map(null, lst) | |||
|
441 | if (fn === null) { | |||
|
442 | return m.extend(null, lst); | |||
|
443 | } | |||
|
444 | // disabled fast path for map(fn, lst) | |||
|
445 | /* | |||
|
446 | if (false && typeof(Array.prototype.map) == 'function') { | |||
|
447 | // Mozilla fast-path | |||
|
448 | return Array.prototype.map.call(lst, fn); | |||
|
449 | } | |||
|
450 | */ | |||
|
451 | var rval = []; | |||
|
452 | for (var i = 0; i < lst.length; i++) { | |||
|
453 | rval.push(fn(lst[i])); | |||
|
454 | } | |||
|
455 | return rval; | |||
|
456 | } else { | |||
|
457 | // default for map(null, ...) is zip(...) | |||
|
458 | if (fn === null) { | |||
|
459 | fn = Array; | |||
|
460 | } | |||
|
461 | var length = null; | |||
|
462 | for (i = 1; i < arguments.length; i++) { | |||
|
463 | // allow iterables to be passed | |||
|
464 | if (!isArrayLike(arguments[i])) { | |||
|
465 | if (itr) { | |||
|
466 | return itr.list(itr.imap.apply(null, arguments)); | |||
|
467 | } else { | |||
|
468 | throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); | |||
|
469 | } | |||
|
470 | } | |||
|
471 | // find the minimum length | |||
|
472 | var l = arguments[i].length; | |||
|
473 | if (length === null || length > l) { | |||
|
474 | length = l; | |||
|
475 | } | |||
|
476 | } | |||
|
477 | rval = []; | |||
|
478 | for (i = 0; i < length; i++) { | |||
|
479 | var args = []; | |||
|
480 | for (var j = 1; j < arguments.length; j++) { | |||
|
481 | args.push(arguments[j][i]); | |||
|
482 | } | |||
|
483 | rval.push(fn.apply(this, args)); | |||
|
484 | } | |||
|
485 | return rval; | |||
|
486 | } | |||
|
487 | }, | |||
|
488 | ||||
|
489 | /** @id MochiKit.Base.xfilter */ | |||
|
490 | xfilter: function (fn/*, obj... */) { | |||
|
491 | var rval = []; | |||
|
492 | if (fn === null) { | |||
|
493 | fn = MochiKit.Base.operator.truth; | |||
|
494 | } | |||
|
495 | for (var i = 1; i < arguments.length; i++) { | |||
|
496 | var o = arguments[i]; | |||
|
497 | if (fn(o)) { | |||
|
498 | rval.push(o); | |||
|
499 | } | |||
|
500 | } | |||
|
501 | return rval; | |||
|
502 | }, | |||
|
503 | ||||
|
504 | /** @id MochiKit.Base.filter */ | |||
|
505 | filter: function (fn, lst, self) { | |||
|
506 | var rval = []; | |||
|
507 | // allow an iterable to be passed | |||
|
508 | var m = MochiKit.Base; | |||
|
509 | if (!m.isArrayLike(lst)) { | |||
|
510 | if (MochiKit.Iter) { | |||
|
511 | lst = MochiKit.Iter.list(lst); | |||
|
512 | } else { | |||
|
513 | throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); | |||
|
514 | } | |||
|
515 | } | |||
|
516 | if (fn === null) { | |||
|
517 | fn = m.operator.truth; | |||
|
518 | } | |||
|
519 | if (typeof(Array.prototype.filter) == 'function') { | |||
|
520 | // Mozilla fast-path | |||
|
521 | return Array.prototype.filter.call(lst, fn, self); | |||
|
522 | } else if (typeof(self) == 'undefined' || self === null) { | |||
|
523 | for (var i = 0; i < lst.length; i++) { | |||
|
524 | var o = lst[i]; | |||
|
525 | if (fn(o)) { | |||
|
526 | rval.push(o); | |||
|
527 | } | |||
|
528 | } | |||
|
529 | } else { | |||
|
530 | for (i = 0; i < lst.length; i++) { | |||
|
531 | o = lst[i]; | |||
|
532 | if (fn.call(self, o)) { | |||
|
533 | rval.push(o); | |||
|
534 | } | |||
|
535 | } | |||
|
536 | } | |||
|
537 | return rval; | |||
|
538 | }, | |||
|
539 | ||||
|
540 | ||||
|
541 | _wrapDumbFunction: function (func) { | |||
|
542 | return function () { | |||
|
543 | // fast path! | |||
|
544 | switch (arguments.length) { | |||
|
545 | case 0: return func(); | |||
|
546 | case 1: return func(arguments[0]); | |||
|
547 | case 2: return func(arguments[0], arguments[1]); | |||
|
548 | case 3: return func(arguments[0], arguments[1], arguments[2]); | |||
|
549 | } | |||
|
550 | var args = []; | |||
|
551 | for (var i = 0; i < arguments.length; i++) { | |||
|
552 | args.push("arguments[" + i + "]"); | |||
|
553 | } | |||
|
554 | return eval("(func(" + args.join(",") + "))"); | |||
|
555 | }; | |||
|
556 | }, | |||
|
557 | ||||
|
558 | /** @id MochiKit.Base.methodcaller */ | |||
|
559 | methodcaller: function (func/*, args... */) { | |||
|
560 | var args = MochiKit.Base.extend(null, arguments, 1); | |||
|
561 | if (typeof(func) == "function") { | |||
|
562 | return function (obj) { | |||
|
563 | return func.apply(obj, args); | |||
|
564 | }; | |||
|
565 | } else { | |||
|
566 | return function (obj) { | |||
|
567 | return obj[func].apply(obj, args); | |||
|
568 | }; | |||
|
569 | } | |||
|
570 | }, | |||
|
571 | ||||
|
572 | /** @id MochiKit.Base.method */ | |||
|
573 | method: function (self, func) { | |||
|
574 | var m = MochiKit.Base; | |||
|
575 | return m.bind.apply(this, m.extend([func, self], arguments, 2)); | |||
|
576 | }, | |||
|
577 | ||||
|
578 | /** @id MochiKit.Base.compose */ | |||
|
579 | compose: function (f1, f2/*, f3, ... fN */) { | |||
|
580 | var fnlist = []; | |||
|
581 | var m = MochiKit.Base; | |||
|
582 | if (arguments.length === 0) { | |||
|
583 | throw new TypeError("compose() requires at least one argument"); | |||
|
584 | } | |||
|
585 | for (var i = 0; i < arguments.length; i++) { | |||
|
586 | var fn = arguments[i]; | |||
|
587 | if (typeof(fn) != "function") { | |||
|
588 | throw new TypeError(m.repr(fn) + " is not a function"); | |||
|
589 | } | |||
|
590 | fnlist.push(fn); | |||
|
591 | } | |||
|
592 | return function () { | |||
|
593 | var args = arguments; | |||
|
594 | for (var i = fnlist.length - 1; i >= 0; i--) { | |||
|
595 | args = [fnlist[i].apply(this, args)]; | |||
|
596 | } | |||
|
597 | return args[0]; | |||
|
598 | }; | |||
|
599 | }, | |||
|
600 | ||||
|
601 | /** @id MochiKit.Base.bind */ | |||
|
602 | bind: function (func, self/* args... */) { | |||
|
603 | if (typeof(func) == "string") { | |||
|
604 | func = self[func]; | |||
|
605 | } | |||
|
606 | var im_func = func.im_func; | |||
|
607 | var im_preargs = func.im_preargs; | |||
|
608 | var im_self = func.im_self; | |||
|
609 | var m = MochiKit.Base; | |||
|
610 | if (typeof(func) == "function" && typeof(func.apply) == "undefined") { | |||
|
611 | // this is for cases where JavaScript sucks ass and gives you a | |||
|
612 | // really dumb built-in function like alert() that doesn't have | |||
|
613 | // an apply | |||
|
614 | func = m._wrapDumbFunction(func); | |||
|
615 | } | |||
|
616 | if (typeof(im_func) != 'function') { | |||
|
617 | im_func = func; | |||
|
618 | } | |||
|
619 | if (typeof(self) != 'undefined') { | |||
|
620 | im_self = self; | |||
|
621 | } | |||
|
622 | if (typeof(im_preargs) == 'undefined') { | |||
|
623 | im_preargs = []; | |||
|
624 | } else { | |||
|
625 | im_preargs = im_preargs.slice(); | |||
|
626 | } | |||
|
627 | m.extend(im_preargs, arguments, 2); | |||
|
628 | var newfunc = function () { | |||
|
629 | var args = arguments; | |||
|
630 | var me = arguments.callee; | |||
|
631 | if (me.im_preargs.length > 0) { | |||
|
632 | args = m.concat(me.im_preargs, args); | |||
|
633 | } | |||
|
634 | var self = me.im_self; | |||
|
635 | if (!self) { | |||
|
636 | self = this; | |||
|
637 | } | |||
|
638 | return me.im_func.apply(self, args); | |||
|
639 | }; | |||
|
640 | newfunc.im_self = im_self; | |||
|
641 | newfunc.im_func = im_func; | |||
|
642 | newfunc.im_preargs = im_preargs; | |||
|
643 | return newfunc; | |||
|
644 | }, | |||
|
645 | ||||
|
646 | /** @id MochiKit.Base.bindMethods */ | |||
|
647 | bindMethods: function (self) { | |||
|
648 | var bind = MochiKit.Base.bind; | |||
|
649 | for (var k in self) { | |||
|
650 | var func = self[k]; | |||
|
651 | if (typeof(func) == 'function') { | |||
|
652 | self[k] = bind(func, self); | |||
|
653 | } | |||
|
654 | } | |||
|
655 | }, | |||
|
656 | ||||
|
657 | /** @id MochiKit.Base.registerComparator */ | |||
|
658 | registerComparator: function (name, check, comparator, /* optional */ override) { | |||
|
659 | MochiKit.Base.comparatorRegistry.register(name, check, comparator, override); | |||
|
660 | }, | |||
|
661 | ||||
|
662 | _primitives: {'boolean': true, 'string': true, 'number': true}, | |||
|
663 | ||||
|
664 | /** @id MochiKit.Base.compare */ | |||
|
665 | compare: function (a, b) { | |||
|
666 | if (a == b) { | |||
|
667 | return 0; | |||
|
668 | } | |||
|
669 | var aIsNull = (typeof(a) == 'undefined' || a === null); | |||
|
670 | var bIsNull = (typeof(b) == 'undefined' || b === null); | |||
|
671 | if (aIsNull && bIsNull) { | |||
|
672 | return 0; | |||
|
673 | } else if (aIsNull) { | |||
|
674 | return -1; | |||
|
675 | } else if (bIsNull) { | |||
|
676 | return 1; | |||
|
677 | } | |||
|
678 | var m = MochiKit.Base; | |||
|
679 | // bool, number, string have meaningful comparisons | |||
|
680 | var prim = m._primitives; | |||
|
681 | if (!(typeof(a) in prim && typeof(b) in prim)) { | |||
|
682 | try { | |||
|
683 | return m.comparatorRegistry.match(a, b); | |||
|
684 | } catch (e) { | |||
|
685 | if (e != m.NotFound) { | |||
|
686 | throw e; | |||
|
687 | } | |||
|
688 | } | |||
|
689 | } | |||
|
690 | if (a < b) { | |||
|
691 | return -1; | |||
|
692 | } else if (a > b) { | |||
|
693 | return 1; | |||
|
694 | } | |||
|
695 | // These types can't be compared | |||
|
696 | var repr = m.repr; | |||
|
697 | throw new TypeError(repr(a) + " and " + repr(b) + " can not be compared"); | |||
|
698 | }, | |||
|
699 | ||||
|
700 | /** @id MochiKit.Base.compareDateLike */ | |||
|
701 | compareDateLike: function (a, b) { | |||
|
702 | return MochiKit.Base.compare(a.getTime(), b.getTime()); | |||
|
703 | }, | |||
|
704 | ||||
|
705 | /** @id MochiKit.Base.compareArrayLike */ | |||
|
706 | compareArrayLike: function (a, b) { | |||
|
707 | var compare = MochiKit.Base.compare; | |||
|
708 | var count = a.length; | |||
|
709 | var rval = 0; | |||
|
710 | if (count > b.length) { | |||
|
711 | rval = 1; | |||
|
712 | count = b.length; | |||
|
713 | } else if (count < b.length) { | |||
|
714 | rval = -1; | |||
|
715 | } | |||
|
716 | for (var i = 0; i < count; i++) { | |||
|
717 | var cmp = compare(a[i], b[i]); | |||
|
718 | if (cmp) { | |||
|
719 | return cmp; | |||
|
720 | } | |||
|
721 | } | |||
|
722 | return rval; | |||
|
723 | }, | |||
|
724 | ||||
|
725 | /** @id MochiKit.Base.registerRepr */ | |||
|
726 | registerRepr: function (name, check, wrap, /* optional */override) { | |||
|
727 | MochiKit.Base.reprRegistry.register(name, check, wrap, override); | |||
|
728 | }, | |||
|
729 | ||||
|
730 | /** @id MochiKit.Base.repr */ | |||
|
731 | repr: function (o) { | |||
|
732 | if (typeof(o) == "undefined") { | |||
|
733 | return "undefined"; | |||
|
734 | } else if (o === null) { | |||
|
735 | return "null"; | |||
|
736 | } | |||
|
737 | try { | |||
|
738 | if (typeof(o.__repr__) == 'function') { | |||
|
739 | return o.__repr__(); | |||
|
740 | } else if (typeof(o.repr) == 'function' && o.repr != arguments.callee) { | |||
|
741 | return o.repr(); | |||
|
742 | } | |||
|
743 | return MochiKit.Base.reprRegistry.match(o); | |||
|
744 | } catch (e) { | |||
|
745 | if (typeof(o.NAME) == 'string' && ( | |||
|
746 | o.toString == Function.prototype.toString || | |||
|
747 | o.toString == Object.prototype.toString | |||
|
748 | )) { | |||
|
749 | return o.NAME; | |||
|
750 | } | |||
|
751 | } | |||
|
752 | try { | |||
|
753 | var ostring = (o + ""); | |||
|
754 | } catch (e) { | |||
|
755 | return "[" + typeof(o) + "]"; | |||
|
756 | } | |||
|
757 | if (typeof(o) == "function") { | |||
|
758 | ostring = ostring.replace(/^\s+/, "").replace(/\s+/g, " "); | |||
|
759 | var idx = ostring.indexOf("{"); | |||
|
760 | if (idx != -1) { | |||
|
761 | ostring = ostring.substr(0, idx) + "{...}"; | |||
|
762 | } | |||
|
763 | } | |||
|
764 | return ostring; | |||
|
765 | }, | |||
|
766 | ||||
|
767 | /** @id MochiKit.Base.reprArrayLike */ | |||
|
768 | reprArrayLike: function (o) { | |||
|
769 | var m = MochiKit.Base; | |||
|
770 | return "[" + m.map(m.repr, o).join(", ") + "]"; | |||
|
771 | }, | |||
|
772 | ||||
|
773 | /** @id MochiKit.Base.reprString */ | |||
|
774 | reprString: function (o) { | |||
|
775 | return ('"' + o.replace(/(["\\])/g, '\\$1') + '"' | |||
|
776 | ).replace(/[\f]/g, "\\f" | |||
|
777 | ).replace(/[\b]/g, "\\b" | |||
|
778 | ).replace(/[\n]/g, "\\n" | |||
|
779 | ).replace(/[\t]/g, "\\t" | |||
|
780 | ).replace(/[\r]/g, "\\r"); | |||
|
781 | }, | |||
|
782 | ||||
|
783 | /** @id MochiKit.Base.reprNumber */ | |||
|
784 | reprNumber: function (o) { | |||
|
785 | return o + ""; | |||
|
786 | }, | |||
|
787 | ||||
|
788 | /** @id MochiKit.Base.registerJSON */ | |||
|
789 | registerJSON: function (name, check, wrap, /* optional */override) { | |||
|
790 | MochiKit.Base.jsonRegistry.register(name, check, wrap, override); | |||
|
791 | }, | |||
|
792 | ||||
|
793 | ||||
|
794 | /** @id MochiKit.Base.evalJSON */ | |||
|
795 | evalJSON: function () { | |||
|
796 | return eval("(" + MochiKit.Base._filterJSON(arguments[0]) + ")"); | |||
|
797 | }, | |||
|
798 | ||||
|
799 | _filterJSON: function (s) { | |||
|
800 | var m = s.match(/^\s*\/\*(.*)\*\/\s*$/); | |||
|
801 | if (m) { | |||
|
802 | return m[1]; | |||
|
803 | } | |||
|
804 | return s; | |||
|
805 | }, | |||
|
806 | ||||
|
807 | /** @id MochiKit.Base.serializeJSON */ | |||
|
808 | serializeJSON: function (o) { | |||
|
809 | var objtype = typeof(o); | |||
|
810 | if (objtype == "number" || objtype == "boolean") { | |||
|
811 | return o + ""; | |||
|
812 | } else if (o === null) { | |||
|
813 | return "null"; | |||
|
814 | } | |||
|
815 | var m = MochiKit.Base; | |||
|
816 | var reprString = m.reprString; | |||
|
817 | if (objtype == "string") { | |||
|
818 | return reprString(o); | |||
|
819 | } | |||
|
820 | // recurse | |||
|
821 | var me = arguments.callee; | |||
|
822 | // short-circuit for objects that support "json" serialization | |||
|
823 | // if they return "self" then just pass-through... | |||
|
824 | var newObj; | |||
|
825 | if (typeof(o.__json__) == "function") { | |||
|
826 | newObj = o.__json__(); | |||
|
827 | if (o !== newObj) { | |||
|
828 | return me(newObj); | |||
|
829 | } | |||
|
830 | } | |||
|
831 | if (typeof(o.json) == "function") { | |||
|
832 | newObj = o.json(); | |||
|
833 | if (o !== newObj) { | |||
|
834 | return me(newObj); | |||
|
835 | } | |||
|
836 | } | |||
|
837 | // array | |||
|
838 | if (objtype != "function" && typeof(o.length) == "number") { | |||
|
839 | var res = []; | |||
|
840 | for (var i = 0; i < o.length; i++) { | |||
|
841 | var val = me(o[i]); | |||
|
842 | if (typeof(val) != "string") { | |||
|
843 | val = "undefined"; | |||
|
844 | } | |||
|
845 | res.push(val); | |||
|
846 | } | |||
|
847 | return "[" + res.join(", ") + "]"; | |||
|
848 | } | |||
|
849 | // look in the registry | |||
|
850 | try { | |||
|
851 | newObj = m.jsonRegistry.match(o); | |||
|
852 | if (o !== newObj) { | |||
|
853 | return me(newObj); | |||
|
854 | } | |||
|
855 | } catch (e) { | |||
|
856 | if (e != m.NotFound) { | |||
|
857 | // something really bad happened | |||
|
858 | throw e; | |||
|
859 | } | |||
|
860 | } | |||
|
861 | // undefined is outside of the spec | |||
|
862 | if (objtype == "undefined") { | |||
|
863 | throw new TypeError("undefined can not be serialized as JSON"); | |||
|
864 | } | |||
|
865 | // it's a function with no adapter, bad | |||
|
866 | if (objtype == "function") { | |||
|
867 | return null; | |||
|
868 | } | |||
|
869 | // generic object code path | |||
|
870 | res = []; | |||
|
871 | for (var k in o) { | |||
|
872 | var useKey; | |||
|
873 | if (typeof(k) == "number") { | |||
|
874 | useKey = '"' + k + '"'; | |||
|
875 | } else if (typeof(k) == "string") { | |||
|
876 | useKey = reprString(k); | |||
|
877 | } else { | |||
|
878 | // skip non-string or number keys | |||
|
879 | continue; | |||
|
880 | } | |||
|
881 | val = me(o[k]); | |||
|
882 | if (typeof(val) != "string") { | |||
|
883 | // skip non-serializable values | |||
|
884 | continue; | |||
|
885 | } | |||
|
886 | res.push(useKey + ":" + val); | |||
|
887 | } | |||
|
888 | return "{" + res.join(", ") + "}"; | |||
|
889 | }, | |||
|
890 | ||||
|
891 | ||||
|
892 | /** @id MochiKit.Base.objEqual */ | |||
|
893 | objEqual: function (a, b) { | |||
|
894 | return (MochiKit.Base.compare(a, b) === 0); | |||
|
895 | }, | |||
|
896 | ||||
|
897 | /** @id MochiKit.Base.arrayEqual */ | |||
|
898 | arrayEqual: function (self, arr) { | |||
|
899 | if (self.length != arr.length) { | |||
|
900 | return false; | |||
|
901 | } | |||
|
902 | return (MochiKit.Base.compare(self, arr) === 0); | |||
|
903 | }, | |||
|
904 | ||||
|
905 | /** @id MochiKit.Base.concat */ | |||
|
906 | concat: function (/* lst... */) { | |||
|
907 | var rval = []; | |||
|
908 | var extend = MochiKit.Base.extend; | |||
|
909 | for (var i = 0; i < arguments.length; i++) { | |||
|
910 | extend(rval, arguments[i]); | |||
|
911 | } | |||
|
912 | return rval; | |||
|
913 | }, | |||
|
914 | ||||
|
915 | /** @id MochiKit.Base.keyComparator */ | |||
|
916 | keyComparator: function (key/* ... */) { | |||
|
917 | // fast-path for single key comparisons | |||
|
918 | var m = MochiKit.Base; | |||
|
919 | var compare = m.compare; | |||
|
920 | if (arguments.length == 1) { | |||
|
921 | return function (a, b) { | |||
|
922 | return compare(a[key], b[key]); | |||
|
923 | }; | |||
|
924 | } | |||
|
925 | var compareKeys = m.extend(null, arguments); | |||
|
926 | return function (a, b) { | |||
|
927 | var rval = 0; | |||
|
928 | // keep comparing until something is inequal or we run out of | |||
|
929 | // keys to compare | |||
|
930 | for (var i = 0; (rval === 0) && (i < compareKeys.length); i++) { | |||
|
931 | var key = compareKeys[i]; | |||
|
932 | rval = compare(a[key], b[key]); | |||
|
933 | } | |||
|
934 | return rval; | |||
|
935 | }; | |||
|
936 | }, | |||
|
937 | ||||
|
938 | /** @id MochiKit.Base.reverseKeyComparator */ | |||
|
939 | reverseKeyComparator: function (key) { | |||
|
940 | var comparator = MochiKit.Base.keyComparator.apply(this, arguments); | |||
|
941 | return function (a, b) { | |||
|
942 | return comparator(b, a); | |||
|
943 | }; | |||
|
944 | }, | |||
|
945 | ||||
|
946 | /** @id MochiKit.Base.partial */ | |||
|
947 | partial: function (func) { | |||
|
948 | var m = MochiKit.Base; | |||
|
949 | return m.bind.apply(this, m.extend([func, undefined], arguments, 1)); | |||
|
950 | }, | |||
|
951 | ||||
|
952 | /** @id MochiKit.Base.listMinMax */ | |||
|
953 | listMinMax: function (which, lst) { | |||
|
954 | if (lst.length === 0) { | |||
|
955 | return null; | |||
|
956 | } | |||
|
957 | var cur = lst[0]; | |||
|
958 | var compare = MochiKit.Base.compare; | |||
|
959 | for (var i = 1; i < lst.length; i++) { | |||
|
960 | var o = lst[i]; | |||
|
961 | if (compare(o, cur) == which) { | |||
|
962 | cur = o; | |||
|
963 | } | |||
|
964 | } | |||
|
965 | return cur; | |||
|
966 | }, | |||
|
967 | ||||
|
968 | /** @id MochiKit.Base.objMax */ | |||
|
969 | objMax: function (/* obj... */) { | |||
|
970 | return MochiKit.Base.listMinMax(1, arguments); | |||
|
971 | }, | |||
|
972 | ||||
|
973 | /** @id MochiKit.Base.objMin */ | |||
|
974 | objMin: function (/* obj... */) { | |||
|
975 | return MochiKit.Base.listMinMax(-1, arguments); | |||
|
976 | }, | |||
|
977 | ||||
|
978 | /** @id MochiKit.Base.findIdentical */ | |||
|
979 | findIdentical: function (lst, value, start/* = 0 */, /* optional */end) { | |||
|
980 | if (typeof(end) == "undefined" || end === null) { | |||
|
981 | end = lst.length; | |||
|
982 | } | |||
|
983 | if (typeof(start) == "undefined" || start === null) { | |||
|
984 | start = 0; | |||
|
985 | } | |||
|
986 | for (var i = start; i < end; i++) { | |||
|
987 | if (lst[i] === value) { | |||
|
988 | return i; | |||
|
989 | } | |||
|
990 | } | |||
|
991 | return -1; | |||
|
992 | }, | |||
|
993 | ||||
|
994 | /** @id MochiKit.Base.mean */ | |||
|
995 | mean: function(/* lst... */) { | |||
|
996 | /* http://www.nist.gov/dads/HTML/mean.html */ | |||
|
997 | var sum = 0; | |||
|
998 | ||||
|
999 | var m = MochiKit.Base; | |||
|
1000 | var args = m.extend(null, arguments); | |||
|
1001 | var count = args.length; | |||
|
1002 | ||||
|
1003 | while (args.length) { | |||
|
1004 | var o = args.shift(); | |||
|
1005 | if (o && typeof(o) == "object" && typeof(o.length) == "number") { | |||
|
1006 | count += o.length - 1; | |||
|
1007 | for (var i = o.length - 1; i >= 0; i--) { | |||
|
1008 | sum += o[i]; | |||
|
1009 | } | |||
|
1010 | } else { | |||
|
1011 | sum += o; | |||
|
1012 | } | |||
|
1013 | } | |||
|
1014 | ||||
|
1015 | if (count <= 0) { | |||
|
1016 | throw new TypeError('mean() requires at least one argument'); | |||
|
1017 | } | |||
|
1018 | ||||
|
1019 | return sum/count; | |||
|
1020 | }, | |||
|
1021 | ||||
|
1022 | /** @id MochiKit.Base.median */ | |||
|
1023 | median: function(/* lst... */) { | |||
|
1024 | /* http://www.nist.gov/dads/HTML/median.html */ | |||
|
1025 | var data = MochiKit.Base.flattenArguments(arguments); | |||
|
1026 | if (data.length === 0) { | |||
|
1027 | throw new TypeError('median() requires at least one argument'); | |||
|
1028 | } | |||
|
1029 | data.sort(compare); | |||
|
1030 | if (data.length % 2 == 0) { | |||
|
1031 | var upper = data.length / 2; | |||
|
1032 | return (data[upper] + data[upper - 1]) / 2; | |||
|
1033 | } else { | |||
|
1034 | return data[(data.length - 1) / 2]; | |||
|
1035 | } | |||
|
1036 | }, | |||
|
1037 | ||||
|
1038 | /** @id MochiKit.Base.findValue */ | |||
|
1039 | findValue: function (lst, value, start/* = 0 */, /* optional */end) { | |||
|
1040 | if (typeof(end) == "undefined" || end === null) { | |||
|
1041 | end = lst.length; | |||
|
1042 | } | |||
|
1043 | if (typeof(start) == "undefined" || start === null) { | |||
|
1044 | start = 0; | |||
|
1045 | } | |||
|
1046 | var cmp = MochiKit.Base.compare; | |||
|
1047 | for (var i = start; i < end; i++) { | |||
|
1048 | if (cmp(lst[i], value) === 0) { | |||
|
1049 | return i; | |||
|
1050 | } | |||
|
1051 | } | |||
|
1052 | return -1; | |||
|
1053 | }, | |||
|
1054 | ||||
|
1055 | /** @id MochiKit.Base.nodeWalk */ | |||
|
1056 | nodeWalk: function (node, visitor) { | |||
|
1057 | var nodes = [node]; | |||
|
1058 | var extend = MochiKit.Base.extend; | |||
|
1059 | while (nodes.length) { | |||
|
1060 | var res = visitor(nodes.shift()); | |||
|
1061 | if (res) { | |||
|
1062 | extend(nodes, res); | |||
|
1063 | } | |||
|
1064 | } | |||
|
1065 | }, | |||
|
1066 | ||||
|
1067 | ||||
|
1068 | /** @id MochiKit.Base.nameFunctions */ | |||
|
1069 | nameFunctions: function (namespace) { | |||
|
1070 | var base = namespace.NAME; | |||
|
1071 | if (typeof(base) == 'undefined') { | |||
|
1072 | base = ''; | |||
|
1073 | } else { | |||
|
1074 | base = base + '.'; | |||
|
1075 | } | |||
|
1076 | for (var name in namespace) { | |||
|
1077 | var o = namespace[name]; | |||
|
1078 | if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') { | |||
|
1079 | try { | |||
|
1080 | o.NAME = base + name; | |||
|
1081 | } catch (e) { | |||
|
1082 | // pass | |||
|
1083 | } | |||
|
1084 | } | |||
|
1085 | } | |||
|
1086 | }, | |||
|
1087 | ||||
|
1088 | ||||
|
1089 | /** @id MochiKit.Base.queryString */ | |||
|
1090 | queryString: function (names, values) { | |||
|
1091 | // check to see if names is a string or a DOM element, and if | |||
|
1092 | // MochiKit.DOM is available. If so, drop it like it's a form | |||
|
1093 | // Ugliest conditional in MochiKit? Probably! | |||
|
1094 | if (typeof(MochiKit.DOM) != "undefined" && arguments.length == 1 | |||
|
1095 | && (typeof(names) == "string" || ( | |||
|
1096 | typeof(names.nodeType) != "undefined" && names.nodeType > 0 | |||
|
1097 | )) | |||
|
1098 | ) { | |||
|
1099 | var kv = MochiKit.DOM.formContents(names); | |||
|
1100 | names = kv[0]; | |||
|
1101 | values = kv[1]; | |||
|
1102 | } else if (arguments.length == 1) { | |||
|
1103 | // Allow the return value of formContents to be passed directly | |||
|
1104 | if (typeof(names.length) == "number" && names.length == 2) { | |||
|
1105 | return arguments.callee(names[0], names[1]); | |||
|
1106 | } | |||
|
1107 | var o = names; | |||
|
1108 | names = []; | |||
|
1109 | values = []; | |||
|
1110 | for (var k in o) { | |||
|
1111 | var v = o[k]; | |||
|
1112 | if (typeof(v) == "function") { | |||
|
1113 | continue; | |||
|
1114 | } else if (MochiKit.Base.isArrayLike(v)){ | |||
|
1115 | for (var i = 0; i < v.length; i++) { | |||
|
1116 | names.push(k); | |||
|
1117 | values.push(v[i]); | |||
|
1118 | } | |||
|
1119 | } else { | |||
|
1120 | names.push(k); | |||
|
1121 | values.push(v); | |||
|
1122 | } | |||
|
1123 | } | |||
|
1124 | } | |||
|
1125 | var rval = []; | |||
|
1126 | var len = Math.min(names.length, values.length); | |||
|
1127 | var urlEncode = MochiKit.Base.urlEncode; | |||
|
1128 | for (var i = 0; i < len; i++) { | |||
|
1129 | v = values[i]; | |||
|
1130 | if (typeof(v) != 'undefined' && v !== null) { | |||
|
1131 | rval.push(urlEncode(names[i]) + "=" + urlEncode(v)); | |||
|
1132 | } | |||
|
1133 | } | |||
|
1134 | return rval.join("&"); | |||
|
1135 | }, | |||
|
1136 | ||||
|
1137 | ||||
|
1138 | /** @id MochiKit.Base.parseQueryString */ | |||
|
1139 | parseQueryString: function (encodedString, useArrays) { | |||
|
1140 | // strip a leading '?' from the encoded string | |||
|
1141 | var qstr = (encodedString.charAt(0) == "?") | |||
|
1142 | ? encodedString.substring(1) | |||
|
1143 | : encodedString; | |||
|
1144 | var pairs = qstr.replace(/\+/g, "%20").split(/(\&\;|\&\#38\;|\&|\&)/); | |||
|
1145 | var o = {}; | |||
|
1146 | var decode; | |||
|
1147 | if (typeof(decodeURIComponent) != "undefined") { | |||
|
1148 | decode = decodeURIComponent; | |||
|
1149 | } else { | |||
|
1150 | decode = unescape; | |||
|
1151 | } | |||
|
1152 | if (useArrays) { | |||
|
1153 | for (var i = 0; i < pairs.length; i++) { | |||
|
1154 | var pair = pairs[i].split("="); | |||
|
1155 | var name = decode(pair.shift()); | |||
|
1156 | if (!name) { | |||
|
1157 | continue; | |||
|
1158 | } | |||
|
1159 | var arr = o[name]; | |||
|
1160 | if (!(arr instanceof Array)) { | |||
|
1161 | arr = []; | |||
|
1162 | o[name] = arr; | |||
|
1163 | } | |||
|
1164 | arr.push(decode(pair.join("="))); | |||
|
1165 | } | |||
|
1166 | } else { | |||
|
1167 | for (i = 0; i < pairs.length; i++) { | |||
|
1168 | pair = pairs[i].split("="); | |||
|
1169 | var name = pair.shift(); | |||
|
1170 | if (!name) { | |||
|
1171 | continue; | |||
|
1172 | } | |||
|
1173 | o[decode(name)] = decode(pair.join("=")); | |||
|
1174 | } | |||
|
1175 | } | |||
|
1176 | return o; | |||
|
1177 | } | |||
|
1178 | }); | |||
|
1179 | ||||
|
1180 | /** @id MochiKit.Base.AdapterRegistry */ | |||
|
1181 | MochiKit.Base.AdapterRegistry = function () { | |||
|
1182 | this.pairs = []; | |||
|
1183 | }; | |||
|
1184 | ||||
|
1185 | MochiKit.Base.AdapterRegistry.prototype = { | |||
|
1186 | /** @id MochiKit.Base.AdapterRegistry.prototype.register */ | |||
|
1187 | register: function (name, check, wrap, /* optional */ override) { | |||
|
1188 | if (override) { | |||
|
1189 | this.pairs.unshift([name, check, wrap]); | |||
|
1190 | } else { | |||
|
1191 | this.pairs.push([name, check, wrap]); | |||
|
1192 | } | |||
|
1193 | }, | |||
|
1194 | ||||
|
1195 | /** @id MochiKit.Base.AdapterRegistry.prototype.match */ | |||
|
1196 | match: function (/* ... */) { | |||
|
1197 | for (var i = 0; i < this.pairs.length; i++) { | |||
|
1198 | var pair = this.pairs[i]; | |||
|
1199 | if (pair[1].apply(this, arguments)) { | |||
|
1200 | return pair[2].apply(this, arguments); | |||
|
1201 | } | |||
|
1202 | } | |||
|
1203 | throw MochiKit.Base.NotFound; | |||
|
1204 | }, | |||
|
1205 | ||||
|
1206 | /** @id MochiKit.Base.AdapterRegistry.prototype.unregister */ | |||
|
1207 | unregister: function (name) { | |||
|
1208 | for (var i = 0; i < this.pairs.length; i++) { | |||
|
1209 | var pair = this.pairs[i]; | |||
|
1210 | if (pair[0] == name) { | |||
|
1211 | this.pairs.splice(i, 1); | |||
|
1212 | return true; | |||
|
1213 | } | |||
|
1214 | } | |||
|
1215 | return false; | |||
|
1216 | } | |||
|
1217 | }; | |||
|
1218 | ||||
|
1219 | ||||
|
1220 | MochiKit.Base.EXPORT = [ | |||
|
1221 | "flattenArray", | |||
|
1222 | "noop", | |||
|
1223 | "camelize", | |||
|
1224 | "counter", | |||
|
1225 | "clone", | |||
|
1226 | "extend", | |||
|
1227 | "update", | |||
|
1228 | "updatetree", | |||
|
1229 | "setdefault", | |||
|
1230 | "keys", | |||
|
1231 | "values", | |||
|
1232 | "items", | |||
|
1233 | "NamedError", | |||
|
1234 | "operator", | |||
|
1235 | "forwardCall", | |||
|
1236 | "itemgetter", | |||
|
1237 | "typeMatcher", | |||
|
1238 | "isCallable", | |||
|
1239 | "isUndefined", | |||
|
1240 | "isUndefinedOrNull", | |||
|
1241 | "isNull", | |||
|
1242 | "isEmpty", | |||
|
1243 | "isNotEmpty", | |||
|
1244 | "isArrayLike", | |||
|
1245 | "isDateLike", | |||
|
1246 | "xmap", | |||
|
1247 | "map", | |||
|
1248 | "xfilter", | |||
|
1249 | "filter", | |||
|
1250 | "methodcaller", | |||
|
1251 | "compose", | |||
|
1252 | "bind", | |||
|
1253 | "bindMethods", | |||
|
1254 | "NotFound", | |||
|
1255 | "AdapterRegistry", | |||
|
1256 | "registerComparator", | |||
|
1257 | "compare", | |||
|
1258 | "registerRepr", | |||
|
1259 | "repr", | |||
|
1260 | "objEqual", | |||
|
1261 | "arrayEqual", | |||
|
1262 | "concat", | |||
|
1263 | "keyComparator", | |||
|
1264 | "reverseKeyComparator", | |||
|
1265 | "partial", | |||
|
1266 | "merge", | |||
|
1267 | "listMinMax", | |||
|
1268 | "listMax", | |||
|
1269 | "listMin", | |||
|
1270 | "objMax", | |||
|
1271 | "objMin", | |||
|
1272 | "nodeWalk", | |||
|
1273 | "zip", | |||
|
1274 | "urlEncode", | |||
|
1275 | "queryString", | |||
|
1276 | "serializeJSON", | |||
|
1277 | "registerJSON", | |||
|
1278 | "evalJSON", | |||
|
1279 | "parseQueryString", | |||
|
1280 | "findValue", | |||
|
1281 | "findIdentical", | |||
|
1282 | "flattenArguments", | |||
|
1283 | "method", | |||
|
1284 | "average", | |||
|
1285 | "mean", | |||
|
1286 | "median" | |||
|
1287 | ]; | |||
|
1288 | ||||
|
1289 | MochiKit.Base.EXPORT_OK = [ | |||
|
1290 | "nameFunctions", | |||
|
1291 | "comparatorRegistry", | |||
|
1292 | "reprRegistry", | |||
|
1293 | "jsonRegistry", | |||
|
1294 | "compareDateLike", | |||
|
1295 | "compareArrayLike", | |||
|
1296 | "reprArrayLike", | |||
|
1297 | "reprString", | |||
|
1298 | "reprNumber" | |||
|
1299 | ]; | |||
|
1300 | ||||
|
1301 | MochiKit.Base._exportSymbols = function (globals, module) { | |||
|
1302 | if (!MochiKit.__export__) { | |||
|
1303 | return; | |||
|
1304 | } | |||
|
1305 | var all = module.EXPORT_TAGS[":all"]; | |||
|
1306 | for (var i = 0; i < all.length; i++) { | |||
|
1307 | globals[all[i]] = module[all[i]]; | |||
|
1308 | } | |||
|
1309 | }; | |||
|
1310 | ||||
|
1311 | MochiKit.Base.__new__ = function () { | |||
|
1312 | // A singleton raised when no suitable adapter is found | |||
|
1313 | var m = this; | |||
|
1314 | ||||
|
1315 | // convenience | |||
|
1316 | /** @id MochiKit.Base.noop */ | |||
|
1317 | m.noop = m.operator.identity; | |||
|
1318 | ||||
|
1319 | // Backwards compat | |||
|
1320 | m.forward = m.forwardCall; | |||
|
1321 | m.find = m.findValue; | |||
|
1322 | ||||
|
1323 | if (typeof(encodeURIComponent) != "undefined") { | |||
|
1324 | /** @id MochiKit.Base.urlEncode */ | |||
|
1325 | m.urlEncode = function (unencoded) { | |||
|
1326 | return encodeURIComponent(unencoded).replace(/\'/g, '%27'); | |||
|
1327 | }; | |||
|
1328 | } else { | |||
|
1329 | m.urlEncode = function (unencoded) { | |||
|
1330 | return escape(unencoded | |||
|
1331 | ).replace(/\+/g, '%2B' | |||
|
1332 | ).replace(/\"/g,'%22' | |||
|
1333 | ).rval.replace(/\'/g, '%27'); | |||
|
1334 | }; | |||
|
1335 | } | |||
|
1336 | ||||
|
1337 | /** @id MochiKit.Base.NamedError */ | |||
|
1338 | m.NamedError = function (name) { | |||
|
1339 | this.message = name; | |||
|
1340 | this.name = name; | |||
|
1341 | }; | |||
|
1342 | m.NamedError.prototype = new Error(); | |||
|
1343 | m.update(m.NamedError.prototype, { | |||
|
1344 | repr: function () { | |||
|
1345 | if (this.message && this.message != this.name) { | |||
|
1346 | return this.name + "(" + m.repr(this.message) + ")"; | |||
|
1347 | } else { | |||
|
1348 | return this.name + "()"; | |||
|
1349 | } | |||
|
1350 | }, | |||
|
1351 | toString: m.forwardCall("repr") | |||
|
1352 | }); | |||
|
1353 | ||||
|
1354 | /** @id MochiKit.Base.NotFound */ | |||
|
1355 | m.NotFound = new m.NamedError("MochiKit.Base.NotFound"); | |||
|
1356 | ||||
|
1357 | ||||
|
1358 | /** @id MochiKit.Base.listMax */ | |||
|
1359 | m.listMax = m.partial(m.listMinMax, 1); | |||
|
1360 | /** @id MochiKit.Base.listMin */ | |||
|
1361 | m.listMin = m.partial(m.listMinMax, -1); | |||
|
1362 | ||||
|
1363 | /** @id MochiKit.Base.isCallable */ | |||
|
1364 | m.isCallable = m.typeMatcher('function'); | |||
|
1365 | /** @id MochiKit.Base.isUndefined */ | |||
|
1366 | m.isUndefined = m.typeMatcher('undefined'); | |||
|
1367 | ||||
|
1368 | /** @id MochiKit.Base.merge */ | |||
|
1369 | m.merge = m.partial(m.update, null); | |||
|
1370 | /** @id MochiKit.Base.zip */ | |||
|
1371 | m.zip = m.partial(m.map, null); | |||
|
1372 | ||||
|
1373 | /** @id MochiKit.Base.average */ | |||
|
1374 | m.average = m.mean; | |||
|
1375 | ||||
|
1376 | /** @id MochiKit.Base.comparatorRegistry */ | |||
|
1377 | m.comparatorRegistry = new m.AdapterRegistry(); | |||
|
1378 | m.registerComparator("dateLike", m.isDateLike, m.compareDateLike); | |||
|
1379 | m.registerComparator("arrayLike", m.isArrayLike, m.compareArrayLike); | |||
|
1380 | ||||
|
1381 | /** @id MochiKit.Base.reprRegistry */ | |||
|
1382 | m.reprRegistry = new m.AdapterRegistry(); | |||
|
1383 | m.registerRepr("arrayLike", m.isArrayLike, m.reprArrayLike); | |||
|
1384 | m.registerRepr("string", m.typeMatcher("string"), m.reprString); | |||
|
1385 | m.registerRepr("numbers", m.typeMatcher("number", "boolean"), m.reprNumber); | |||
|
1386 | ||||
|
1387 | /** @id MochiKit.Base.jsonRegistry */ | |||
|
1388 | m.jsonRegistry = new m.AdapterRegistry(); | |||
|
1389 | ||||
|
1390 | var all = m.concat(m.EXPORT, m.EXPORT_OK); | |||
|
1391 | m.EXPORT_TAGS = { | |||
|
1392 | ":common": m.concat(m.EXPORT_OK), | |||
|
1393 | ":all": all | |||
|
1394 | }; | |||
|
1395 | ||||
|
1396 | m.nameFunctions(this); | |||
|
1397 | ||||
|
1398 | }; | |||
|
1399 | ||||
|
1400 | MochiKit.Base.__new__(); | |||
|
1401 | ||||
|
1402 | // | |||
|
1403 | // XXX: Internet Explorer blows | |||
|
1404 | // | |||
|
1405 | if (MochiKit.__export__) { | |||
|
1406 | compare = MochiKit.Base.compare; | |||
|
1407 | compose = MochiKit.Base.compose; | |||
|
1408 | serializeJSON = MochiKit.Base.serializeJSON; | |||
|
1409 | mean = MochiKit.Base.mean; | |||
|
1410 | median = MochiKit.Base.median; | |||
|
1411 | } | |||
|
1412 | ||||
|
1413 | MochiKit.Base._exportSymbols(this, MochiKit.Base); |
This diff has been collapsed as it changes many lines, (902 lines changed) Show them Hide them | |||||
@@ -0,0 +1,902 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.Color 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito and others. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.Color'); | |||
|
13 | dojo.require('MochiKit.Base'); | |||
|
14 | dojo.require('MochiKit.DOM'); | |||
|
15 | dojo.require('MochiKit.Style'); | |||
|
16 | } | |||
|
17 | ||||
|
18 | if (typeof(JSAN) != 'undefined') { | |||
|
19 | JSAN.use("MochiKit.Base", []); | |||
|
20 | JSAN.use("MochiKit.DOM", []); | |||
|
21 | JSAN.use("MochiKit.Style", []); | |||
|
22 | } | |||
|
23 | ||||
|
24 | try { | |||
|
25 | if (typeof(MochiKit.Base) == 'undefined') { | |||
|
26 | throw ""; | |||
|
27 | } | |||
|
28 | } catch (e) { | |||
|
29 | throw "MochiKit.Color depends on MochiKit.Base"; | |||
|
30 | } | |||
|
31 | ||||
|
32 | try { | |||
|
33 | if (typeof(MochiKit.DOM) == 'undefined') { | |||
|
34 | throw ""; | |||
|
35 | } | |||
|
36 | } catch (e) { | |||
|
37 | throw "MochiKit.Color depends on MochiKit.DOM"; | |||
|
38 | } | |||
|
39 | ||||
|
40 | try { | |||
|
41 | if (typeof(MochiKit.Style) == 'undefined') { | |||
|
42 | throw ""; | |||
|
43 | } | |||
|
44 | } catch (e) { | |||
|
45 | throw "MochiKit.Color depends on MochiKit.Style"; | |||
|
46 | } | |||
|
47 | ||||
|
48 | if (typeof(MochiKit.Color) == "undefined") { | |||
|
49 | MochiKit.Color = {}; | |||
|
50 | } | |||
|
51 | ||||
|
52 | MochiKit.Color.NAME = "MochiKit.Color"; | |||
|
53 | MochiKit.Color.VERSION = "1.4"; | |||
|
54 | ||||
|
55 | MochiKit.Color.__repr__ = function () { | |||
|
56 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
57 | }; | |||
|
58 | ||||
|
59 | MochiKit.Color.toString = function () { | |||
|
60 | return this.__repr__(); | |||
|
61 | }; | |||
|
62 | ||||
|
63 | ||||
|
64 | /** @id MochiKit.Color.Color */ | |||
|
65 | MochiKit.Color.Color = function (red, green, blue, alpha) { | |||
|
66 | if (typeof(alpha) == 'undefined' || alpha === null) { | |||
|
67 | alpha = 1.0; | |||
|
68 | } | |||
|
69 | this.rgb = { | |||
|
70 | r: red, | |||
|
71 | g: green, | |||
|
72 | b: blue, | |||
|
73 | a: alpha | |||
|
74 | }; | |||
|
75 | }; | |||
|
76 | ||||
|
77 | ||||
|
78 | // Prototype methods | |||
|
79 | ||||
|
80 | MochiKit.Color.Color.prototype = { | |||
|
81 | ||||
|
82 | __class__: MochiKit.Color.Color, | |||
|
83 | ||||
|
84 | /** @id MochiKit.Color.Color.prototype.colorWithAlpha */ | |||
|
85 | colorWithAlpha: function (alpha) { | |||
|
86 | var rgb = this.rgb; | |||
|
87 | var m = MochiKit.Color; | |||
|
88 | return m.Color.fromRGB(rgb.r, rgb.g, rgb.b, alpha); | |||
|
89 | }, | |||
|
90 | ||||
|
91 | /** @id MochiKit.Color.Color.prototype.colorWithHue */ | |||
|
92 | colorWithHue: function (hue) { | |||
|
93 | // get an HSL model, and set the new hue... | |||
|
94 | var hsl = this.asHSL(); | |||
|
95 | hsl.h = hue; | |||
|
96 | var m = MochiKit.Color; | |||
|
97 | // convert back to RGB... | |||
|
98 | return m.Color.fromHSL(hsl); | |||
|
99 | }, | |||
|
100 | ||||
|
101 | /** @id MochiKit.Color.Color.prototype.colorWithSaturation */ | |||
|
102 | colorWithSaturation: function (saturation) { | |||
|
103 | // get an HSL model, and set the new hue... | |||
|
104 | var hsl = this.asHSL(); | |||
|
105 | hsl.s = saturation; | |||
|
106 | var m = MochiKit.Color; | |||
|
107 | // convert back to RGB... | |||
|
108 | return m.Color.fromHSL(hsl); | |||
|
109 | }, | |||
|
110 | ||||
|
111 | /** @id MochiKit.Color.Color.prototype.colorWithLightness */ | |||
|
112 | colorWithLightness: function (lightness) { | |||
|
113 | // get an HSL model, and set the new hue... | |||
|
114 | var hsl = this.asHSL(); | |||
|
115 | hsl.l = lightness; | |||
|
116 | var m = MochiKit.Color; | |||
|
117 | // convert back to RGB... | |||
|
118 | return m.Color.fromHSL(hsl); | |||
|
119 | }, | |||
|
120 | ||||
|
121 | /** @id MochiKit.Color.Color.prototype.darkerColorWithLevel */ | |||
|
122 | darkerColorWithLevel: function (level) { | |||
|
123 | var hsl = this.asHSL(); | |||
|
124 | hsl.l = Math.max(hsl.l - level, 0); | |||
|
125 | var m = MochiKit.Color; | |||
|
126 | return m.Color.fromHSL(hsl); | |||
|
127 | }, | |||
|
128 | ||||
|
129 | /** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */ | |||
|
130 | lighterColorWithLevel: function (level) { | |||
|
131 | var hsl = this.asHSL(); | |||
|
132 | hsl.l = Math.min(hsl.l + level, 1); | |||
|
133 | var m = MochiKit.Color; | |||
|
134 | return m.Color.fromHSL(hsl); | |||
|
135 | }, | |||
|
136 | ||||
|
137 | /** @id MochiKit.Color.Color.prototype.blendedColor */ | |||
|
138 | blendedColor: function (other, /* optional */ fraction) { | |||
|
139 | if (typeof(fraction) == 'undefined' || fraction === null) { | |||
|
140 | fraction = 0.5; | |||
|
141 | } | |||
|
142 | var sf = 1.0 - fraction; | |||
|
143 | var s = this.rgb; | |||
|
144 | var d = other.rgb; | |||
|
145 | var df = fraction; | |||
|
146 | return MochiKit.Color.Color.fromRGB( | |||
|
147 | (s.r * sf) + (d.r * df), | |||
|
148 | (s.g * sf) + (d.g * df), | |||
|
149 | (s.b * sf) + (d.b * df), | |||
|
150 | (s.a * sf) + (d.a * df) | |||
|
151 | ); | |||
|
152 | }, | |||
|
153 | ||||
|
154 | /** @id MochiKit.Color.Color.prototype.compareRGB */ | |||
|
155 | compareRGB: function (other) { | |||
|
156 | var a = this.asRGB(); | |||
|
157 | var b = other.asRGB(); | |||
|
158 | return MochiKit.Base.compare( | |||
|
159 | [a.r, a.g, a.b, a.a], | |||
|
160 | [b.r, b.g, b.b, b.a] | |||
|
161 | ); | |||
|
162 | }, | |||
|
163 | ||||
|
164 | /** @id MochiKit.Color.Color.prototype.isLight */ | |||
|
165 | isLight: function () { | |||
|
166 | return this.asHSL().b > 0.5; | |||
|
167 | }, | |||
|
168 | ||||
|
169 | /** @id MochiKit.Color.Color.prototype.isDark */ | |||
|
170 | isDark: function () { | |||
|
171 | return (!this.isLight()); | |||
|
172 | }, | |||
|
173 | ||||
|
174 | /** @id MochiKit.Color.Color.prototype.toHSLString */ | |||
|
175 | toHSLString: function () { | |||
|
176 | var c = this.asHSL(); | |||
|
177 | var ccc = MochiKit.Color.clampColorComponent; | |||
|
178 | var rval = this._hslString; | |||
|
179 | if (!rval) { | |||
|
180 | var mid = ( | |||
|
181 | ccc(c.h, 360).toFixed(0) | |||
|
182 | + "," + ccc(c.s, 100).toPrecision(4) + "%" | |||
|
183 | + "," + ccc(c.l, 100).toPrecision(4) + "%" | |||
|
184 | ); | |||
|
185 | var a = c.a; | |||
|
186 | if (a >= 1) { | |||
|
187 | a = 1; | |||
|
188 | rval = "hsl(" + mid + ")"; | |||
|
189 | } else { | |||
|
190 | if (a <= 0) { | |||
|
191 | a = 0; | |||
|
192 | } | |||
|
193 | rval = "hsla(" + mid + "," + a + ")"; | |||
|
194 | } | |||
|
195 | this._hslString = rval; | |||
|
196 | } | |||
|
197 | return rval; | |||
|
198 | }, | |||
|
199 | ||||
|
200 | /** @id MochiKit.Color.Color.prototype.toRGBString */ | |||
|
201 | toRGBString: function () { | |||
|
202 | var c = this.rgb; | |||
|
203 | var ccc = MochiKit.Color.clampColorComponent; | |||
|
204 | var rval = this._rgbString; | |||
|
205 | if (!rval) { | |||
|
206 | var mid = ( | |||
|
207 | ccc(c.r, 255).toFixed(0) | |||
|
208 | + "," + ccc(c.g, 255).toFixed(0) | |||
|
209 | + "," + ccc(c.b, 255).toFixed(0) | |||
|
210 | ); | |||
|
211 | if (c.a != 1) { | |||
|
212 | rval = "rgba(" + mid + "," + c.a + ")"; | |||
|
213 | } else { | |||
|
214 | rval = "rgb(" + mid + ")"; | |||
|
215 | } | |||
|
216 | this._rgbString = rval; | |||
|
217 | } | |||
|
218 | return rval; | |||
|
219 | }, | |||
|
220 | ||||
|
221 | /** @id MochiKit.Color.Color.prototype.asRGB */ | |||
|
222 | asRGB: function () { | |||
|
223 | return MochiKit.Base.clone(this.rgb); | |||
|
224 | }, | |||
|
225 | ||||
|
226 | /** @id MochiKit.Color.Color.prototype.toHexString */ | |||
|
227 | toHexString: function () { | |||
|
228 | var m = MochiKit.Color; | |||
|
229 | var c = this.rgb; | |||
|
230 | var ccc = MochiKit.Color.clampColorComponent; | |||
|
231 | var rval = this._hexString; | |||
|
232 | if (!rval) { | |||
|
233 | rval = ("#" + | |||
|
234 | m.toColorPart(ccc(c.r, 255)) + | |||
|
235 | m.toColorPart(ccc(c.g, 255)) + | |||
|
236 | m.toColorPart(ccc(c.b, 255)) | |||
|
237 | ); | |||
|
238 | this._hexString = rval; | |||
|
239 | } | |||
|
240 | return rval; | |||
|
241 | }, | |||
|
242 | ||||
|
243 | /** @id MochiKit.Color.Color.prototype.asHSV */ | |||
|
244 | asHSV: function () { | |||
|
245 | var hsv = this.hsv; | |||
|
246 | var c = this.rgb; | |||
|
247 | if (typeof(hsv) == 'undefined' || hsv === null) { | |||
|
248 | hsv = MochiKit.Color.rgbToHSV(this.rgb); | |||
|
249 | this.hsv = hsv; | |||
|
250 | } | |||
|
251 | return MochiKit.Base.clone(hsv); | |||
|
252 | }, | |||
|
253 | ||||
|
254 | /** @id MochiKit.Color.Color.prototype.asHSL */ | |||
|
255 | asHSL: function () { | |||
|
256 | var hsl = this.hsl; | |||
|
257 | var c = this.rgb; | |||
|
258 | if (typeof(hsl) == 'undefined' || hsl === null) { | |||
|
259 | hsl = MochiKit.Color.rgbToHSL(this.rgb); | |||
|
260 | this.hsl = hsl; | |||
|
261 | } | |||
|
262 | return MochiKit.Base.clone(hsl); | |||
|
263 | }, | |||
|
264 | ||||
|
265 | /** @id MochiKit.Color.Color.prototype.toString */ | |||
|
266 | toString: function () { | |||
|
267 | return this.toRGBString(); | |||
|
268 | }, | |||
|
269 | ||||
|
270 | /** @id MochiKit.Color.Color.prototype.repr */ | |||
|
271 | repr: function () { | |||
|
272 | var c = this.rgb; | |||
|
273 | var col = [c.r, c.g, c.b, c.a]; | |||
|
274 | return this.__class__.NAME + "(" + col.join(", ") + ")"; | |||
|
275 | } | |||
|
276 | ||||
|
277 | }; | |||
|
278 | ||||
|
279 | // Constructor methods | |||
|
280 | ||||
|
281 | MochiKit.Base.update(MochiKit.Color.Color, { | |||
|
282 | /** @id MochiKit.Color.Color.fromRGB */ | |||
|
283 | fromRGB: function (red, green, blue, alpha) { | |||
|
284 | // designated initializer | |||
|
285 | var Color = MochiKit.Color.Color; | |||
|
286 | if (arguments.length == 1) { | |||
|
287 | var rgb = red; | |||
|
288 | red = rgb.r; | |||
|
289 | green = rgb.g; | |||
|
290 | blue = rgb.b; | |||
|
291 | if (typeof(rgb.a) == 'undefined') { | |||
|
292 | alpha = undefined; | |||
|
293 | } else { | |||
|
294 | alpha = rgb.a; | |||
|
295 | } | |||
|
296 | } | |||
|
297 | return new Color(red, green, blue, alpha); | |||
|
298 | }, | |||
|
299 | ||||
|
300 | /** @id MochiKit.Color.Color.fromHSL */ | |||
|
301 | fromHSL: function (hue, saturation, lightness, alpha) { | |||
|
302 | var m = MochiKit.Color; | |||
|
303 | return m.Color.fromRGB(m.hslToRGB.apply(m, arguments)); | |||
|
304 | }, | |||
|
305 | ||||
|
306 | /** @id MochiKit.Color.Color.fromHSV */ | |||
|
307 | fromHSV: function (hue, saturation, value, alpha) { | |||
|
308 | var m = MochiKit.Color; | |||
|
309 | return m.Color.fromRGB(m.hsvToRGB.apply(m, arguments)); | |||
|
310 | }, | |||
|
311 | ||||
|
312 | /** @id MochiKit.Color.Color.fromName */ | |||
|
313 | fromName: function (name) { | |||
|
314 | var Color = MochiKit.Color.Color; | |||
|
315 | // Opera 9 seems to "quote" named colors(?!) | |||
|
316 | if (name.charAt(0) == '"') { | |||
|
317 | name = name.substr(1, name.length - 2); | |||
|
318 | } | |||
|
319 | var htmlColor = Color._namedColors[name.toLowerCase()]; | |||
|
320 | if (typeof(htmlColor) == 'string') { | |||
|
321 | return Color.fromHexString(htmlColor); | |||
|
322 | } else if (name == "transparent") { | |||
|
323 | return Color.transparentColor(); | |||
|
324 | } | |||
|
325 | return null; | |||
|
326 | }, | |||
|
327 | ||||
|
328 | /** @id MochiKit.Color.Color.fromString */ | |||
|
329 | fromString: function (colorString) { | |||
|
330 | var self = MochiKit.Color.Color; | |||
|
331 | var three = colorString.substr(0, 3); | |||
|
332 | if (three == "rgb") { | |||
|
333 | return self.fromRGBString(colorString); | |||
|
334 | } else if (three == "hsl") { | |||
|
335 | return self.fromHSLString(colorString); | |||
|
336 | } else if (colorString.charAt(0) == "#") { | |||
|
337 | return self.fromHexString(colorString); | |||
|
338 | } | |||
|
339 | return self.fromName(colorString); | |||
|
340 | }, | |||
|
341 | ||||
|
342 | ||||
|
343 | /** @id MochiKit.Color.Color.fromHexString */ | |||
|
344 | fromHexString: function (hexCode) { | |||
|
345 | if (hexCode.charAt(0) == '#') { | |||
|
346 | hexCode = hexCode.substring(1); | |||
|
347 | } | |||
|
348 | var components = []; | |||
|
349 | var i, hex; | |||
|
350 | if (hexCode.length == 3) { | |||
|
351 | for (i = 0; i < 3; i++) { | |||
|
352 | hex = hexCode.substr(i, 1); | |||
|
353 | components.push(parseInt(hex + hex, 16) / 255.0); | |||
|
354 | } | |||
|
355 | } else { | |||
|
356 | for (i = 0; i < 6; i += 2) { | |||
|
357 | hex = hexCode.substr(i, 2); | |||
|
358 | components.push(parseInt(hex, 16) / 255.0); | |||
|
359 | } | |||
|
360 | } | |||
|
361 | var Color = MochiKit.Color.Color; | |||
|
362 | return Color.fromRGB.apply(Color, components); | |||
|
363 | }, | |||
|
364 | ||||
|
365 | ||||
|
366 | _fromColorString: function (pre, method, scales, colorCode) { | |||
|
367 | // parses either HSL or RGB | |||
|
368 | if (colorCode.indexOf(pre) === 0) { | |||
|
369 | colorCode = colorCode.substring(colorCode.indexOf("(", 3) + 1, colorCode.length - 1); | |||
|
370 | } | |||
|
371 | var colorChunks = colorCode.split(/\s*,\s*/); | |||
|
372 | var colorFloats = []; | |||
|
373 | for (var i = 0; i < colorChunks.length; i++) { | |||
|
374 | var c = colorChunks[i]; | |||
|
375 | var val; | |||
|
376 | var three = c.substring(c.length - 3); | |||
|
377 | if (c.charAt(c.length - 1) == '%') { | |||
|
378 | val = 0.01 * parseFloat(c.substring(0, c.length - 1)); | |||
|
379 | } else if (three == "deg") { | |||
|
380 | val = parseFloat(c) / 360.0; | |||
|
381 | } else if (three == "rad") { | |||
|
382 | val = parseFloat(c) / (Math.PI * 2); | |||
|
383 | } else { | |||
|
384 | val = scales[i] * parseFloat(c); | |||
|
385 | } | |||
|
386 | colorFloats.push(val); | |||
|
387 | } | |||
|
388 | return this[method].apply(this, colorFloats); | |||
|
389 | }, | |||
|
390 | ||||
|
391 | /** @id MochiKit.Color.Color.fromComputedStyle */ | |||
|
392 | fromComputedStyle: function (elem, style) { | |||
|
393 | var d = MochiKit.DOM; | |||
|
394 | var cls = MochiKit.Color.Color; | |||
|
395 | for (elem = d.getElement(elem); elem; elem = elem.parentNode) { | |||
|
396 | var actualColor = MochiKit.Style.getStyle.apply(d, arguments); | |||
|
397 | if (!actualColor) { | |||
|
398 | continue; | |||
|
399 | } | |||
|
400 | var color = cls.fromString(actualColor); | |||
|
401 | if (!color) { | |||
|
402 | break; | |||
|
403 | } | |||
|
404 | if (color.asRGB().a > 0) { | |||
|
405 | return color; | |||
|
406 | } | |||
|
407 | } | |||
|
408 | return null; | |||
|
409 | }, | |||
|
410 | ||||
|
411 | /** @id MochiKit.Color.Color.fromBackground */ | |||
|
412 | fromBackground: function (elem) { | |||
|
413 | var cls = MochiKit.Color.Color; | |||
|
414 | return cls.fromComputedStyle( | |||
|
415 | elem, "backgroundColor", "background-color") || cls.whiteColor(); | |||
|
416 | }, | |||
|
417 | ||||
|
418 | /** @id MochiKit.Color.Color.fromText */ | |||
|
419 | fromText: function (elem) { | |||
|
420 | var cls = MochiKit.Color.Color; | |||
|
421 | return cls.fromComputedStyle( | |||
|
422 | elem, "color", "color") || cls.blackColor(); | |||
|
423 | }, | |||
|
424 | ||||
|
425 | /** @id MochiKit.Color.Color.namedColors */ | |||
|
426 | namedColors: function () { | |||
|
427 | return MochiKit.Base.clone(MochiKit.Color.Color._namedColors); | |||
|
428 | } | |||
|
429 | }); | |||
|
430 | ||||
|
431 | ||||
|
432 | // Module level functions | |||
|
433 | ||||
|
434 | MochiKit.Base.update(MochiKit.Color, { | |||
|
435 | /** @id MochiKit.Color.clampColorComponent */ | |||
|
436 | clampColorComponent: function (v, scale) { | |||
|
437 | v *= scale; | |||
|
438 | if (v < 0) { | |||
|
439 | return 0; | |||
|
440 | } else if (v > scale) { | |||
|
441 | return scale; | |||
|
442 | } else { | |||
|
443 | return v; | |||
|
444 | } | |||
|
445 | }, | |||
|
446 | ||||
|
447 | _hslValue: function (n1, n2, hue) { | |||
|
448 | if (hue > 6.0) { | |||
|
449 | hue -= 6.0; | |||
|
450 | } else if (hue < 0.0) { | |||
|
451 | hue += 6.0; | |||
|
452 | } | |||
|
453 | var val; | |||
|
454 | if (hue < 1.0) { | |||
|
455 | val = n1 + (n2 - n1) * hue; | |||
|
456 | } else if (hue < 3.0) { | |||
|
457 | val = n2; | |||
|
458 | } else if (hue < 4.0) { | |||
|
459 | val = n1 + (n2 - n1) * (4.0 - hue); | |||
|
460 | } else { | |||
|
461 | val = n1; | |||
|
462 | } | |||
|
463 | return val; | |||
|
464 | }, | |||
|
465 | ||||
|
466 | /** @id MochiKit.Color.hsvToRGB */ | |||
|
467 | hsvToRGB: function (hue, saturation, value, alpha) { | |||
|
468 | if (arguments.length == 1) { | |||
|
469 | var hsv = hue; | |||
|
470 | hue = hsv.h; | |||
|
471 | saturation = hsv.s; | |||
|
472 | value = hsv.v; | |||
|
473 | alpha = hsv.a; | |||
|
474 | } | |||
|
475 | var red; | |||
|
476 | var green; | |||
|
477 | var blue; | |||
|
478 | if (saturation === 0) { | |||
|
479 | red = value; | |||
|
480 | green = value; | |||
|
481 | blue = value; | |||
|
482 | } else { | |||
|
483 | var i = Math.floor(hue * 6); | |||
|
484 | var f = (hue * 6) - i; | |||
|
485 | var p = value * (1 - saturation); | |||
|
486 | var q = value * (1 - (saturation * f)); | |||
|
487 | var t = value * (1 - (saturation * (1 - f))); | |||
|
488 | switch (i) { | |||
|
489 | case 1: red = q; green = value; blue = p; break; | |||
|
490 | case 2: red = p; green = value; blue = t; break; | |||
|
491 | case 3: red = p; green = q; blue = value; break; | |||
|
492 | case 4: red = t; green = p; blue = value; break; | |||
|
493 | case 5: red = value; green = p; blue = q; break; | |||
|
494 | case 6: // fall through | |||
|
495 | case 0: red = value; green = t; blue = p; break; | |||
|
496 | } | |||
|
497 | } | |||
|
498 | return { | |||
|
499 | r: red, | |||
|
500 | g: green, | |||
|
501 | b: blue, | |||
|
502 | a: alpha | |||
|
503 | }; | |||
|
504 | }, | |||
|
505 | ||||
|
506 | /** @id MochiKit.Color.hslToRGB */ | |||
|
507 | hslToRGB: function (hue, saturation, lightness, alpha) { | |||
|
508 | if (arguments.length == 1) { | |||
|
509 | var hsl = hue; | |||
|
510 | hue = hsl.h; | |||
|
511 | saturation = hsl.s; | |||
|
512 | lightness = hsl.l; | |||
|
513 | alpha = hsl.a; | |||
|
514 | } | |||
|
515 | var red; | |||
|
516 | var green; | |||
|
517 | var blue; | |||
|
518 | if (saturation === 0) { | |||
|
519 | red = lightness; | |||
|
520 | green = lightness; | |||
|
521 | blue = lightness; | |||
|
522 | } else { | |||
|
523 | var m2; | |||
|
524 | if (lightness <= 0.5) { | |||
|
525 | m2 = lightness * (1.0 + saturation); | |||
|
526 | } else { | |||
|
527 | m2 = lightness + saturation - (lightness * saturation); | |||
|
528 | } | |||
|
529 | var m1 = (2.0 * lightness) - m2; | |||
|
530 | var f = MochiKit.Color._hslValue; | |||
|
531 | var h6 = hue * 6.0; | |||
|
532 | red = f(m1, m2, h6 + 2); | |||
|
533 | green = f(m1, m2, h6); | |||
|
534 | blue = f(m1, m2, h6 - 2); | |||
|
535 | } | |||
|
536 | return { | |||
|
537 | r: red, | |||
|
538 | g: green, | |||
|
539 | b: blue, | |||
|
540 | a: alpha | |||
|
541 | }; | |||
|
542 | }, | |||
|
543 | ||||
|
544 | /** @id MochiKit.Color.rgbToHSV */ | |||
|
545 | rgbToHSV: function (red, green, blue, alpha) { | |||
|
546 | if (arguments.length == 1) { | |||
|
547 | var rgb = red; | |||
|
548 | red = rgb.r; | |||
|
549 | green = rgb.g; | |||
|
550 | blue = rgb.b; | |||
|
551 | alpha = rgb.a; | |||
|
552 | } | |||
|
553 | var max = Math.max(Math.max(red, green), blue); | |||
|
554 | var min = Math.min(Math.min(red, green), blue); | |||
|
555 | var hue; | |||
|
556 | var saturation; | |||
|
557 | var value = max; | |||
|
558 | if (min == max) { | |||
|
559 | hue = 0; | |||
|
560 | saturation = 0; | |||
|
561 | } else { | |||
|
562 | var delta = (max - min); | |||
|
563 | saturation = delta / max; | |||
|
564 | ||||
|
565 | if (red == max) { | |||
|
566 | hue = (green - blue) / delta; | |||
|
567 | } else if (green == max) { | |||
|
568 | hue = 2 + ((blue - red) / delta); | |||
|
569 | } else { | |||
|
570 | hue = 4 + ((red - green) / delta); | |||
|
571 | } | |||
|
572 | hue /= 6; | |||
|
573 | if (hue < 0) { | |||
|
574 | hue += 1; | |||
|
575 | } | |||
|
576 | if (hue > 1) { | |||
|
577 | hue -= 1; | |||
|
578 | } | |||
|
579 | } | |||
|
580 | return { | |||
|
581 | h: hue, | |||
|
582 | s: saturation, | |||
|
583 | v: value, | |||
|
584 | a: alpha | |||
|
585 | }; | |||
|
586 | }, | |||
|
587 | ||||
|
588 | /** @id MochiKit.Color.rgbToHSL */ | |||
|
589 | rgbToHSL: function (red, green, blue, alpha) { | |||
|
590 | if (arguments.length == 1) { | |||
|
591 | var rgb = red; | |||
|
592 | red = rgb.r; | |||
|
593 | green = rgb.g; | |||
|
594 | blue = rgb.b; | |||
|
595 | alpha = rgb.a; | |||
|
596 | } | |||
|
597 | var max = Math.max(red, Math.max(green, blue)); | |||
|
598 | var min = Math.min(red, Math.min(green, blue)); | |||
|
599 | var hue; | |||
|
600 | var saturation; | |||
|
601 | var lightness = (max + min) / 2.0; | |||
|
602 | var delta = max - min; | |||
|
603 | if (delta === 0) { | |||
|
604 | hue = 0; | |||
|
605 | saturation = 0; | |||
|
606 | } else { | |||
|
607 | if (lightness <= 0.5) { | |||
|
608 | saturation = delta / (max + min); | |||
|
609 | } else { | |||
|
610 | saturation = delta / (2 - max - min); | |||
|
611 | } | |||
|
612 | if (red == max) { | |||
|
613 | hue = (green - blue) / delta; | |||
|
614 | } else if (green == max) { | |||
|
615 | hue = 2 + ((blue - red) / delta); | |||
|
616 | } else { | |||
|
617 | hue = 4 + ((red - green) / delta); | |||
|
618 | } | |||
|
619 | hue /= 6; | |||
|
620 | if (hue < 0) { | |||
|
621 | hue += 1; | |||
|
622 | } | |||
|
623 | if (hue > 1) { | |||
|
624 | hue -= 1; | |||
|
625 | } | |||
|
626 | ||||
|
627 | } | |||
|
628 | return { | |||
|
629 | h: hue, | |||
|
630 | s: saturation, | |||
|
631 | l: lightness, | |||
|
632 | a: alpha | |||
|
633 | }; | |||
|
634 | }, | |||
|
635 | ||||
|
636 | /** @id MochiKit.Color.toColorPart */ | |||
|
637 | toColorPart: function (num) { | |||
|
638 | num = Math.round(num); | |||
|
639 | var digits = num.toString(16); | |||
|
640 | if (num < 16) { | |||
|
641 | return '0' + digits; | |||
|
642 | } | |||
|
643 | return digits; | |||
|
644 | }, | |||
|
645 | ||||
|
646 | __new__: function () { | |||
|
647 | var m = MochiKit.Base; | |||
|
648 | /** @id MochiKit.Color.fromRGBString */ | |||
|
649 | this.Color.fromRGBString = m.bind( | |||
|
650 | this.Color._fromColorString, this.Color, "rgb", "fromRGB", | |||
|
651 | [1.0/255.0, 1.0/255.0, 1.0/255.0, 1] | |||
|
652 | ); | |||
|
653 | /** @id MochiKit.Color.fromHSLString */ | |||
|
654 | this.Color.fromHSLString = m.bind( | |||
|
655 | this.Color._fromColorString, this.Color, "hsl", "fromHSL", | |||
|
656 | [1.0/360.0, 0.01, 0.01, 1] | |||
|
657 | ); | |||
|
658 | ||||
|
659 | var third = 1.0 / 3.0; | |||
|
660 | /** @id MochiKit.Color.colors */ | |||
|
661 | var colors = { | |||
|
662 | // NSColor colors plus transparent | |||
|
663 | /** @id MochiKit.Color.blackColor */ | |||
|
664 | black: [0, 0, 0], | |||
|
665 | /** @id MochiKit.Color.blueColor */ | |||
|
666 | blue: [0, 0, 1], | |||
|
667 | /** @id MochiKit.Color.brownColor */ | |||
|
668 | brown: [0.6, 0.4, 0.2], | |||
|
669 | /** @id MochiKit.Color.cyanColor */ | |||
|
670 | cyan: [0, 1, 1], | |||
|
671 | /** @id MochiKit.Color.darkGrayColor */ | |||
|
672 | darkGray: [third, third, third], | |||
|
673 | /** @id MochiKit.Color.grayColor */ | |||
|
674 | gray: [0.5, 0.5, 0.5], | |||
|
675 | /** @id MochiKit.Color.greenColor */ | |||
|
676 | green: [0, 1, 0], | |||
|
677 | /** @id MochiKit.Color.lightGrayColor */ | |||
|
678 | lightGray: [2 * third, 2 * third, 2 * third], | |||
|
679 | /** @id MochiKit.Color.magentaColor */ | |||
|
680 | magenta: [1, 0, 1], | |||
|
681 | /** @id MochiKit.Color.orangeColor */ | |||
|
682 | orange: [1, 0.5, 0], | |||
|
683 | /** @id MochiKit.Color.purpleColor */ | |||
|
684 | purple: [0.5, 0, 0.5], | |||
|
685 | /** @id MochiKit.Color.redColor */ | |||
|
686 | red: [1, 0, 0], | |||
|
687 | /** @id MochiKit.Color.transparentColor */ | |||
|
688 | transparent: [0, 0, 0, 0], | |||
|
689 | /** @id MochiKit.Color.whiteColor */ | |||
|
690 | white: [1, 1, 1], | |||
|
691 | /** @id MochiKit.Color.yellowColor */ | |||
|
692 | yellow: [1, 1, 0] | |||
|
693 | }; | |||
|
694 | ||||
|
695 | var makeColor = function (name, r, g, b, a) { | |||
|
696 | var rval = this.fromRGB(r, g, b, a); | |||
|
697 | this[name] = function () { return rval; }; | |||
|
698 | return rval; | |||
|
699 | }; | |||
|
700 | ||||
|
701 | for (var k in colors) { | |||
|
702 | var name = k + "Color"; | |||
|
703 | var bindArgs = m.concat( | |||
|
704 | [makeColor, this.Color, name], | |||
|
705 | colors[k] | |||
|
706 | ); | |||
|
707 | this.Color[name] = m.bind.apply(null, bindArgs); | |||
|
708 | } | |||
|
709 | ||||
|
710 | var isColor = function () { | |||
|
711 | for (var i = 0; i < arguments.length; i++) { | |||
|
712 | if (!(arguments[i] instanceof Color)) { | |||
|
713 | return false; | |||
|
714 | } | |||
|
715 | } | |||
|
716 | return true; | |||
|
717 | }; | |||
|
718 | ||||
|
719 | var compareColor = function (a, b) { | |||
|
720 | return a.compareRGB(b); | |||
|
721 | }; | |||
|
722 | ||||
|
723 | m.nameFunctions(this); | |||
|
724 | ||||
|
725 | m.registerComparator(this.Color.NAME, isColor, compareColor); | |||
|
726 | ||||
|
727 | this.EXPORT_TAGS = { | |||
|
728 | ":common": this.EXPORT, | |||
|
729 | ":all": m.concat(this.EXPORT, this.EXPORT_OK) | |||
|
730 | }; | |||
|
731 | ||||
|
732 | } | |||
|
733 | }); | |||
|
734 | ||||
|
735 | MochiKit.Color.EXPORT = [ | |||
|
736 | "Color" | |||
|
737 | ]; | |||
|
738 | ||||
|
739 | MochiKit.Color.EXPORT_OK = [ | |||
|
740 | "clampColorComponent", | |||
|
741 | "rgbToHSL", | |||
|
742 | "hslToRGB", | |||
|
743 | "rgbToHSV", | |||
|
744 | "hsvToRGB", | |||
|
745 | "toColorPart" | |||
|
746 | ]; | |||
|
747 | ||||
|
748 | MochiKit.Color.__new__(); | |||
|
749 | ||||
|
750 | MochiKit.Base._exportSymbols(this, MochiKit.Color); | |||
|
751 | ||||
|
752 | // Full table of css3 X11 colors <http://www.w3.org/TR/css3-color/#X11COLORS> | |||
|
753 | ||||
|
754 | MochiKit.Color.Color._namedColors = { | |||
|
755 | aliceblue: "#f0f8ff", | |||
|
756 | antiquewhite: "#faebd7", | |||
|
757 | aqua: "#00ffff", | |||
|
758 | aquamarine: "#7fffd4", | |||
|
759 | azure: "#f0ffff", | |||
|
760 | beige: "#f5f5dc", | |||
|
761 | bisque: "#ffe4c4", | |||
|
762 | black: "#000000", | |||
|
763 | blanchedalmond: "#ffebcd", | |||
|
764 | blue: "#0000ff", | |||
|
765 | blueviolet: "#8a2be2", | |||
|
766 | brown: "#a52a2a", | |||
|
767 | burlywood: "#deb887", | |||
|
768 | cadetblue: "#5f9ea0", | |||
|
769 | chartreuse: "#7fff00", | |||
|
770 | chocolate: "#d2691e", | |||
|
771 | coral: "#ff7f50", | |||
|
772 | cornflowerblue: "#6495ed", | |||
|
773 | cornsilk: "#fff8dc", | |||
|
774 | crimson: "#dc143c", | |||
|
775 | cyan: "#00ffff", | |||
|
776 | darkblue: "#00008b", | |||
|
777 | darkcyan: "#008b8b", | |||
|
778 | darkgoldenrod: "#b8860b", | |||
|
779 | darkgray: "#a9a9a9", | |||
|
780 | darkgreen: "#006400", | |||
|
781 | darkgrey: "#a9a9a9", | |||
|
782 | darkkhaki: "#bdb76b", | |||
|
783 | darkmagenta: "#8b008b", | |||
|
784 | darkolivegreen: "#556b2f", | |||
|
785 | darkorange: "#ff8c00", | |||
|
786 | darkorchid: "#9932cc", | |||
|
787 | darkred: "#8b0000", | |||
|
788 | darksalmon: "#e9967a", | |||
|
789 | darkseagreen: "#8fbc8f", | |||
|
790 | darkslateblue: "#483d8b", | |||
|
791 | darkslategray: "#2f4f4f", | |||
|
792 | darkslategrey: "#2f4f4f", | |||
|
793 | darkturquoise: "#00ced1", | |||
|
794 | darkviolet: "#9400d3", | |||
|
795 | deeppink: "#ff1493", | |||
|
796 | deepskyblue: "#00bfff", | |||
|
797 | dimgray: "#696969", | |||
|
798 | dimgrey: "#696969", | |||
|
799 | dodgerblue: "#1e90ff", | |||
|
800 | firebrick: "#b22222", | |||
|
801 | floralwhite: "#fffaf0", | |||
|
802 | forestgreen: "#228b22", | |||
|
803 | fuchsia: "#ff00ff", | |||
|
804 | gainsboro: "#dcdcdc", | |||
|
805 | ghostwhite: "#f8f8ff", | |||
|
806 | gold: "#ffd700", | |||
|
807 | goldenrod: "#daa520", | |||
|
808 | gray: "#808080", | |||
|
809 | green: "#008000", | |||
|
810 | greenyellow: "#adff2f", | |||
|
811 | grey: "#808080", | |||
|
812 | honeydew: "#f0fff0", | |||
|
813 | hotpink: "#ff69b4", | |||
|
814 | indianred: "#cd5c5c", | |||
|
815 | indigo: "#4b0082", | |||
|
816 | ivory: "#fffff0", | |||
|
817 | khaki: "#f0e68c", | |||
|
818 | lavender: "#e6e6fa", | |||
|
819 | lavenderblush: "#fff0f5", | |||
|
820 | lawngreen: "#7cfc00", | |||
|
821 | lemonchiffon: "#fffacd", | |||
|
822 | lightblue: "#add8e6", | |||
|
823 | lightcoral: "#f08080", | |||
|
824 | lightcyan: "#e0ffff", | |||
|
825 | lightgoldenrodyellow: "#fafad2", | |||
|
826 | lightgray: "#d3d3d3", | |||
|
827 | lightgreen: "#90ee90", | |||
|
828 | lightgrey: "#d3d3d3", | |||
|
829 | lightpink: "#ffb6c1", | |||
|
830 | lightsalmon: "#ffa07a", | |||
|
831 | lightseagreen: "#20b2aa", | |||
|
832 | lightskyblue: "#87cefa", | |||
|
833 | lightslategray: "#778899", | |||
|
834 | lightslategrey: "#778899", | |||
|
835 | lightsteelblue: "#b0c4de", | |||
|
836 | lightyellow: "#ffffe0", | |||
|
837 | lime: "#00ff00", | |||
|
838 | limegreen: "#32cd32", | |||
|
839 | linen: "#faf0e6", | |||
|
840 | magenta: "#ff00ff", | |||
|
841 | maroon: "#800000", | |||
|
842 | mediumaquamarine: "#66cdaa", | |||
|
843 | mediumblue: "#0000cd", | |||
|
844 | mediumorchid: "#ba55d3", | |||
|
845 | mediumpurple: "#9370db", | |||
|
846 | mediumseagreen: "#3cb371", | |||
|
847 | mediumslateblue: "#7b68ee", | |||
|
848 | mediumspringgreen: "#00fa9a", | |||
|
849 | mediumturquoise: "#48d1cc", | |||
|
850 | mediumvioletred: "#c71585", | |||
|
851 | midnightblue: "#191970", | |||
|
852 | mintcream: "#f5fffa", | |||
|
853 | mistyrose: "#ffe4e1", | |||
|
854 | moccasin: "#ffe4b5", | |||
|
855 | navajowhite: "#ffdead", | |||
|
856 | navy: "#000080", | |||
|
857 | oldlace: "#fdf5e6", | |||
|
858 | olive: "#808000", | |||
|
859 | olivedrab: "#6b8e23", | |||
|
860 | orange: "#ffa500", | |||
|
861 | orangered: "#ff4500", | |||
|
862 | orchid: "#da70d6", | |||
|
863 | palegoldenrod: "#eee8aa", | |||
|
864 | palegreen: "#98fb98", | |||
|
865 | paleturquoise: "#afeeee", | |||
|
866 | palevioletred: "#db7093", | |||
|
867 | papayawhip: "#ffefd5", | |||
|
868 | peachpuff: "#ffdab9", | |||
|
869 | peru: "#cd853f", | |||
|
870 | pink: "#ffc0cb", | |||
|
871 | plum: "#dda0dd", | |||
|
872 | powderblue: "#b0e0e6", | |||
|
873 | purple: "#800080", | |||
|
874 | red: "#ff0000", | |||
|
875 | rosybrown: "#bc8f8f", | |||
|
876 | royalblue: "#4169e1", | |||
|
877 | saddlebrown: "#8b4513", | |||
|
878 | salmon: "#fa8072", | |||
|
879 | sandybrown: "#f4a460", | |||
|
880 | seagreen: "#2e8b57", | |||
|
881 | seashell: "#fff5ee", | |||
|
882 | sienna: "#a0522d", | |||
|
883 | silver: "#c0c0c0", | |||
|
884 | skyblue: "#87ceeb", | |||
|
885 | slateblue: "#6a5acd", | |||
|
886 | slategray: "#708090", | |||
|
887 | slategrey: "#708090", | |||
|
888 | snow: "#fffafa", | |||
|
889 | springgreen: "#00ff7f", | |||
|
890 | steelblue: "#4682b4", | |||
|
891 | tan: "#d2b48c", | |||
|
892 | teal: "#008080", | |||
|
893 | thistle: "#d8bfd8", | |||
|
894 | tomato: "#ff6347", | |||
|
895 | turquoise: "#40e0d0", | |||
|
896 | violet: "#ee82ee", | |||
|
897 | wheat: "#f5deb3", | |||
|
898 | white: "#ffffff", | |||
|
899 | whitesmoke: "#f5f5f5", | |||
|
900 | yellow: "#ffff00", | |||
|
901 | yellowgreen: "#9acd32" | |||
|
902 | }; |
This diff has been collapsed as it changes many lines, (1281 lines changed) Show them Hide them | |||||
@@ -0,0 +1,1281 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.DOM 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide("MochiKit.DOM"); | |||
|
13 | dojo.require("MochiKit.Base"); | |||
|
14 | } | |||
|
15 | if (typeof(JSAN) != 'undefined') { | |||
|
16 | JSAN.use("MochiKit.Base", []); | |||
|
17 | } | |||
|
18 | ||||
|
19 | try { | |||
|
20 | if (typeof(MochiKit.Base) == 'undefined') { | |||
|
21 | throw ""; | |||
|
22 | } | |||
|
23 | } catch (e) { | |||
|
24 | throw "MochiKit.DOM depends on MochiKit.Base!"; | |||
|
25 | } | |||
|
26 | ||||
|
27 | if (typeof(MochiKit.DOM) == 'undefined') { | |||
|
28 | MochiKit.DOM = {}; | |||
|
29 | } | |||
|
30 | ||||
|
31 | MochiKit.DOM.NAME = "MochiKit.DOM"; | |||
|
32 | MochiKit.DOM.VERSION = "1.4"; | |||
|
33 | MochiKit.DOM.__repr__ = function () { | |||
|
34 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
35 | }; | |||
|
36 | MochiKit.DOM.toString = function () { | |||
|
37 | return this.__repr__(); | |||
|
38 | }; | |||
|
39 | ||||
|
40 | MochiKit.DOM.EXPORT = [ | |||
|
41 | "removeEmptyTextNodes", | |||
|
42 | "formContents", | |||
|
43 | "currentWindow", | |||
|
44 | "currentDocument", | |||
|
45 | "withWindow", | |||
|
46 | "withDocument", | |||
|
47 | "registerDOMConverter", | |||
|
48 | "coerceToDOM", | |||
|
49 | "createDOM", | |||
|
50 | "createDOMFunc", | |||
|
51 | "isChildNode", | |||
|
52 | "getNodeAttribute", | |||
|
53 | "removeNodeAttribute", | |||
|
54 | "setNodeAttribute", | |||
|
55 | "updateNodeAttributes", | |||
|
56 | "appendChildNodes", | |||
|
57 | "insertSiblingNodesAfter", | |||
|
58 | "insertSiblingNodesBefore", | |||
|
59 | "replaceChildNodes", | |||
|
60 | "removeElement", | |||
|
61 | "swapDOM", | |||
|
62 | "BUTTON", | |||
|
63 | "TT", | |||
|
64 | "PRE", | |||
|
65 | "H1", | |||
|
66 | "H2", | |||
|
67 | "H3", | |||
|
68 | "BR", | |||
|
69 | "CANVAS", | |||
|
70 | "HR", | |||
|
71 | "LABEL", | |||
|
72 | "TEXTAREA", | |||
|
73 | "FORM", | |||
|
74 | "STRONG", | |||
|
75 | "SELECT", | |||
|
76 | "OPTION", | |||
|
77 | "OPTGROUP", | |||
|
78 | "LEGEND", | |||
|
79 | "FIELDSET", | |||
|
80 | "P", | |||
|
81 | "UL", | |||
|
82 | "OL", | |||
|
83 | "LI", | |||
|
84 | "TD", | |||
|
85 | "TR", | |||
|
86 | "THEAD", | |||
|
87 | "TBODY", | |||
|
88 | "TFOOT", | |||
|
89 | "TABLE", | |||
|
90 | "TH", | |||
|
91 | "INPUT", | |||
|
92 | "SPAN", | |||
|
93 | "A", | |||
|
94 | "DIV", | |||
|
95 | "IMG", | |||
|
96 | "getElement", | |||
|
97 | "$", | |||
|
98 | "getElementsByTagAndClassName", | |||
|
99 | "addToCallStack", | |||
|
100 | "addLoadEvent", | |||
|
101 | "focusOnLoad", | |||
|
102 | "setElementClass", | |||
|
103 | "toggleElementClass", | |||
|
104 | "addElementClass", | |||
|
105 | "removeElementClass", | |||
|
106 | "swapElementClass", | |||
|
107 | "hasElementClass", | |||
|
108 | "escapeHTML", | |||
|
109 | "toHTML", | |||
|
110 | "emitHTML", | |||
|
111 | "scrapeText", | |||
|
112 | "isParent", | |||
|
113 | "getFirstParentByTagAndClassName", | |||
|
114 | "makeClipping", | |||
|
115 | "undoClipping", | |||
|
116 | "makePositioned", | |||
|
117 | "undoPositioned", | |||
|
118 | "getFirstElementByTagAndClassName" | |||
|
119 | ]; | |||
|
120 | ||||
|
121 | MochiKit.DOM.EXPORT_OK = [ | |||
|
122 | "domConverters" | |||
|
123 | ]; | |||
|
124 | ||||
|
125 | MochiKit.DOM.DEPRECATED = [ | |||
|
126 | ['computedStyle', 'MochiKit.Style.getStyle', '1.4'], | |||
|
127 | /** @id MochiKit.DOM.elementDimensions */ | |||
|
128 | ['elementDimensions', 'MochiKit.Style.getElementDimensions', '1.4'], | |||
|
129 | /** @id MochiKit.DOM.elementPosition */ | |||
|
130 | ['elementPosition', 'MochiKit.Style.getElementPosition', '1.4'], | |||
|
131 | ['hideElement', 'MochiKit.Style.hideElement', '1.4'], | |||
|
132 | /** @id MochiKit.DOM.setElementDimensions */ | |||
|
133 | ['setElementDimensions', 'MochiKit.Style.setElementDimensions', '1.4'], | |||
|
134 | /** @id MochiKit.DOM.setElementPosition */ | |||
|
135 | ['setElementPosition', 'MochiKit.Style.setElementPosition', '1.4'], | |||
|
136 | ['setDisplayForElement', 'MochiKit.Style.setDisplayForElement', '1.4'], | |||
|
137 | /** @id MochiKit.DOM.setOpacity */ | |||
|
138 | ['setOpacity', 'MochiKit.Style.setOpacity', '1.4'], | |||
|
139 | ['showElement', 'MochiKit.Style.showElement', '1.4'], | |||
|
140 | /** @id MochiKit.DOM.Coordinates */ | |||
|
141 | ['Coordinates', 'MochiKit.Style.Coordinates', '1.4'], // FIXME: broken | |||
|
142 | /** @id MochiKit.DOM.Dimensions */ | |||
|
143 | ['Dimensions', 'MochiKit.Style.Dimensions', '1.4'] // FIXME: broken | |||
|
144 | ]; | |||
|
145 | ||||
|
146 | /** @id MochiKit.DOM.getViewportDimensions */ | |||
|
147 | MochiKit.DOM.getViewportDimensions = new Function('' + | |||
|
148 | 'if (!MochiKit["Style"]) {' + | |||
|
149 | ' throw new Error("This function has been deprecated and depends on MochiKit.Style.");' + | |||
|
150 | '}' + | |||
|
151 | 'return MochiKit.Style.getViewportDimensions.apply(this, arguments);'); | |||
|
152 | ||||
|
153 | MochiKit.Base.update(MochiKit.DOM, { | |||
|
154 | ||||
|
155 | /** @id MochiKit.DOM.currentWindow */ | |||
|
156 | currentWindow: function () { | |||
|
157 | return MochiKit.DOM._window; | |||
|
158 | }, | |||
|
159 | ||||
|
160 | /** @id MochiKit.DOM.currentDocument */ | |||
|
161 | currentDocument: function () { | |||
|
162 | return MochiKit.DOM._document; | |||
|
163 | }, | |||
|
164 | ||||
|
165 | /** @id MochiKit.DOM.withWindow */ | |||
|
166 | withWindow: function (win, func) { | |||
|
167 | var self = MochiKit.DOM; | |||
|
168 | var oldDoc = self._document; | |||
|
169 | var oldWin = self._window; | |||
|
170 | var rval; | |||
|
171 | try { | |||
|
172 | self._window = win; | |||
|
173 | self._document = win.document; | |||
|
174 | rval = func(); | |||
|
175 | } catch (e) { | |||
|
176 | self._window = oldWin; | |||
|
177 | self._document = oldDoc; | |||
|
178 | throw e; | |||
|
179 | } | |||
|
180 | self._window = oldWin; | |||
|
181 | self._document = oldDoc; | |||
|
182 | return rval; | |||
|
183 | }, | |||
|
184 | ||||
|
185 | /** @id MochiKit.DOM.formContents */ | |||
|
186 | formContents: function (elem/* = document.body */) { | |||
|
187 | var names = []; | |||
|
188 | var values = []; | |||
|
189 | var m = MochiKit.Base; | |||
|
190 | var self = MochiKit.DOM; | |||
|
191 | if (typeof(elem) == "undefined" || elem === null) { | |||
|
192 | elem = self._document.body; | |||
|
193 | } else { | |||
|
194 | elem = self.getElement(elem); | |||
|
195 | } | |||
|
196 | m.nodeWalk(elem, function (elem) { | |||
|
197 | var name = elem.name; | |||
|
198 | if (m.isNotEmpty(name)) { | |||
|
199 | var tagName = elem.tagName.toUpperCase(); | |||
|
200 | if (tagName === "INPUT" | |||
|
201 | && (elem.type == "radio" || elem.type == "checkbox") | |||
|
202 | && !elem.checked | |||
|
203 | ) { | |||
|
204 | return null; | |||
|
205 | } | |||
|
206 | if (tagName === "SELECT") { | |||
|
207 | if (elem.type == "select-one") { | |||
|
208 | if (elem.selectedIndex >= 0) { | |||
|
209 | var opt = elem.options[elem.selectedIndex]; | |||
|
210 | var v = opt.value; | |||
|
211 | if (!v) { | |||
|
212 | var h = opt.outerHTML; | |||
|
213 | // internet explorer sure does suck. | |||
|
214 | if (h && !h.match(/^[^>]+\svalue\s*=/i)) { | |||
|
215 | v = opt.text; | |||
|
216 | } | |||
|
217 | } | |||
|
218 | names.push(name); | |||
|
219 | values.push(v); | |||
|
220 | return null; | |||
|
221 | } | |||
|
222 | // no form elements? | |||
|
223 | names.push(name); | |||
|
224 | values.push(""); | |||
|
225 | return null; | |||
|
226 | } else { | |||
|
227 | var opts = elem.options; | |||
|
228 | if (!opts.length) { | |||
|
229 | names.push(name); | |||
|
230 | values.push(""); | |||
|
231 | return null; | |||
|
232 | } | |||
|
233 | for (var i = 0; i < opts.length; i++) { | |||
|
234 | var opt = opts[i]; | |||
|
235 | if (!opt.selected) { | |||
|
236 | continue; | |||
|
237 | } | |||
|
238 | var v = opt.value; | |||
|
239 | if (!v) { | |||
|
240 | var h = opt.outerHTML; | |||
|
241 | // internet explorer sure does suck. | |||
|
242 | if (h && !h.match(/^[^>]+\svalue\s*=/i)) { | |||
|
243 | v = opt.text; | |||
|
244 | } | |||
|
245 | } | |||
|
246 | names.push(name); | |||
|
247 | values.push(v); | |||
|
248 | } | |||
|
249 | return null; | |||
|
250 | } | |||
|
251 | } | |||
|
252 | if (tagName === "FORM" || tagName === "P" || tagName === "SPAN" | |||
|
253 | || tagName === "DIV" | |||
|
254 | ) { | |||
|
255 | return elem.childNodes; | |||
|
256 | } | |||
|
257 | names.push(name); | |||
|
258 | values.push(elem.value || ''); | |||
|
259 | return null; | |||
|
260 | } | |||
|
261 | return elem.childNodes; | |||
|
262 | }); | |||
|
263 | return [names, values]; | |||
|
264 | }, | |||
|
265 | ||||
|
266 | /** @id MochiKit.DOM.withDocument */ | |||
|
267 | withDocument: function (doc, func) { | |||
|
268 | var self = MochiKit.DOM; | |||
|
269 | var oldDoc = self._document; | |||
|
270 | var rval; | |||
|
271 | try { | |||
|
272 | self._document = doc; | |||
|
273 | rval = func(); | |||
|
274 | } catch (e) { | |||
|
275 | self._document = oldDoc; | |||
|
276 | throw e; | |||
|
277 | } | |||
|
278 | self._document = oldDoc; | |||
|
279 | return rval; | |||
|
280 | }, | |||
|
281 | ||||
|
282 | /** @id MochiKit.DOM.registerDOMConverter */ | |||
|
283 | registerDOMConverter: function (name, check, wrap, /* optional */override) { | |||
|
284 | MochiKit.DOM.domConverters.register(name, check, wrap, override); | |||
|
285 | }, | |||
|
286 | ||||
|
287 | /** @id MochiKit.DOM.coerceToDOM */ | |||
|
288 | coerceToDOM: function (node, ctx) { | |||
|
289 | var m = MochiKit.Base; | |||
|
290 | var im = MochiKit.Iter; | |||
|
291 | var self = MochiKit.DOM; | |||
|
292 | if (im) { | |||
|
293 | var iter = im.iter; | |||
|
294 | var repeat = im.repeat; | |||
|
295 | var map = m.map; | |||
|
296 | } | |||
|
297 | var domConverters = self.domConverters; | |||
|
298 | var coerceToDOM = arguments.callee; | |||
|
299 | var NotFound = m.NotFound; | |||
|
300 | while (true) { | |||
|
301 | if (typeof(node) == 'undefined' || node === null) { | |||
|
302 | return null; | |||
|
303 | } | |||
|
304 | // this is a safari childNodes object, avoiding crashes w/ attr | |||
|
305 | // lookup | |||
|
306 | if (typeof(node) == "function" && | |||
|
307 | typeof(node.length) == "number" && | |||
|
308 | !(node instanceof Function)) { | |||
|
309 | node = im.list(node); | |||
|
310 | } | |||
|
311 | if (typeof(node.nodeType) != 'undefined' && node.nodeType > 0) { | |||
|
312 | return node; | |||
|
313 | } | |||
|
314 | if (typeof(node) == 'number' || typeof(node) == 'boolean') { | |||
|
315 | node = node.toString(); | |||
|
316 | // FALL THROUGH | |||
|
317 | } | |||
|
318 | if (typeof(node) == 'string') { | |||
|
319 | return self._document.createTextNode(node); | |||
|
320 | } | |||
|
321 | if (typeof(node.__dom__) == 'function') { | |||
|
322 | node = node.__dom__(ctx); | |||
|
323 | continue; | |||
|
324 | } | |||
|
325 | if (typeof(node.dom) == 'function') { | |||
|
326 | node = node.dom(ctx); | |||
|
327 | continue; | |||
|
328 | } | |||
|
329 | if (typeof(node) == 'function') { | |||
|
330 | node = node.apply(ctx, [ctx]); | |||
|
331 | continue; | |||
|
332 | } | |||
|
333 | ||||
|
334 | if (im) { | |||
|
335 | // iterable | |||
|
336 | var iterNodes = null; | |||
|
337 | try { | |||
|
338 | iterNodes = iter(node); | |||
|
339 | } catch (e) { | |||
|
340 | // pass | |||
|
341 | } | |||
|
342 | if (iterNodes) { | |||
|
343 | return map(coerceToDOM, iterNodes, repeat(ctx)); | |||
|
344 | } | |||
|
345 | } | |||
|
346 | ||||
|
347 | // adapter | |||
|
348 | try { | |||
|
349 | node = domConverters.match(node, ctx); | |||
|
350 | continue; | |||
|
351 | } catch (e) { | |||
|
352 | if (e != NotFound) { | |||
|
353 | throw e; | |||
|
354 | } | |||
|
355 | } | |||
|
356 | ||||
|
357 | // fallback | |||
|
358 | return self._document.createTextNode(node.toString()); | |||
|
359 | } | |||
|
360 | // mozilla warnings aren't too bright | |||
|
361 | return undefined; | |||
|
362 | }, | |||
|
363 | ||||
|
364 | /** @id MochiKit.DOM.isChildNode */ | |||
|
365 | isChildNode: function (node, maybeparent) { | |||
|
366 | var self = MochiKit.DOM; | |||
|
367 | if (typeof(node) == "string") { | |||
|
368 | node = self.getElement(node); | |||
|
369 | } | |||
|
370 | if (typeof(maybeparent) == "string") { | |||
|
371 | maybeparent = self.getElement(maybeparent); | |||
|
372 | } | |||
|
373 | if (typeof(node) == 'undefined' || node === null || node === self._document) { | |||
|
374 | return false; | |||
|
375 | } | |||
|
376 | do { | |||
|
377 | if (node === maybeparent) { | |||
|
378 | return true; | |||
|
379 | } | |||
|
380 | var tagName = node.tagName; | |||
|
381 | node = node.parentNode; | |||
|
382 | if (!tagName) { | |||
|
383 | break; | |||
|
384 | } | |||
|
385 | tagName = tagName.toUpperCase(); | |||
|
386 | } while (tagName != "BODY" && tagName != "HTML"); | |||
|
387 | return false; | |||
|
388 | }, | |||
|
389 | ||||
|
390 | /** @id MochiKit.DOM.setNodeAttribute */ | |||
|
391 | setNodeAttribute: function (node, attr, value) { | |||
|
392 | var o = {}; | |||
|
393 | o[attr] = value; | |||
|
394 | try { | |||
|
395 | return MochiKit.DOM.updateNodeAttributes(node, o); | |||
|
396 | } catch (e) { | |||
|
397 | // pass | |||
|
398 | } | |||
|
399 | return null; | |||
|
400 | }, | |||
|
401 | ||||
|
402 | /** @id MochiKit.DOM.getNodeAttribute */ | |||
|
403 | getNodeAttribute: function (node, attr) { | |||
|
404 | var self = MochiKit.DOM; | |||
|
405 | var rename = self.attributeArray.renames[attr]; | |||
|
406 | node = self.getElement(node); | |||
|
407 | try { | |||
|
408 | if (rename) { | |||
|
409 | return node[rename]; | |||
|
410 | } | |||
|
411 | return node.getAttribute(attr); | |||
|
412 | } catch (e) { | |||
|
413 | // pass | |||
|
414 | } | |||
|
415 | return null; | |||
|
416 | }, | |||
|
417 | ||||
|
418 | /** @id MochiKit.DOM.removeNodeAttribute */ | |||
|
419 | removeNodeAttribute: function (node, attr) { | |||
|
420 | var self = MochiKit.DOM; | |||
|
421 | var rename = self.attributeArray.renames[attr]; | |||
|
422 | node = self.getElement(node); | |||
|
423 | try { | |||
|
424 | if (rename) { | |||
|
425 | return node[rename]; | |||
|
426 | } | |||
|
427 | return node.removeAttribute(attr); | |||
|
428 | } catch (e) { | |||
|
429 | // pass | |||
|
430 | } | |||
|
431 | return null; | |||
|
432 | }, | |||
|
433 | ||||
|
434 | /** @id MochiKit.DOM.updateNodeAttributes */ | |||
|
435 | updateNodeAttributes: function (node, attrs) { | |||
|
436 | var elem = node; | |||
|
437 | var self = MochiKit.DOM; | |||
|
438 | if (typeof(node) == 'string') { | |||
|
439 | elem = self.getElement(node); | |||
|
440 | } | |||
|
441 | if (attrs) { | |||
|
442 | var updatetree = MochiKit.Base.updatetree; | |||
|
443 | if (self.attributeArray.compliant) { | |||
|
444 | // not IE, good. | |||
|
445 | for (var k in attrs) { | |||
|
446 | var v = attrs[k]; | |||
|
447 | if (typeof(v) == 'object' && typeof(elem[k]) == 'object') { | |||
|
448 | if (k == "style" && MochiKit.Style) { | |||
|
449 | MochiKit.Style.setStyle(elem, v); | |||
|
450 | } else { | |||
|
451 | updatetree(elem[k], v); | |||
|
452 | } | |||
|
453 | } else if (k.substring(0, 2) == "on") { | |||
|
454 | if (typeof(v) == "string") { | |||
|
455 | v = new Function(v); | |||
|
456 | } | |||
|
457 | elem[k] = v; | |||
|
458 | } else { | |||
|
459 | elem.setAttribute(k, v); | |||
|
460 | } | |||
|
461 | } | |||
|
462 | } else { | |||
|
463 | // IE is insane in the membrane | |||
|
464 | var renames = self.attributeArray.renames; | |||
|
465 | for (var k in attrs) { | |||
|
466 | v = attrs[k]; | |||
|
467 | var renamed = renames[k]; | |||
|
468 | if (k == "style" && typeof(v) == "string") { | |||
|
469 | elem.style.cssText = v; | |||
|
470 | } else if (typeof(renamed) == "string") { | |||
|
471 | elem[renamed] = v; | |||
|
472 | } else if (typeof(elem[k]) == 'object' | |||
|
473 | && typeof(v) == 'object') { | |||
|
474 | if (k == "style" && MochiKit.Style) { | |||
|
475 | MochiKit.Style.setStyle(elem, v); | |||
|
476 | } else { | |||
|
477 | updatetree(elem[k], v); | |||
|
478 | } | |||
|
479 | } else if (k.substring(0, 2) == "on") { | |||
|
480 | if (typeof(v) == "string") { | |||
|
481 | v = new Function(v); | |||
|
482 | } | |||
|
483 | elem[k] = v; | |||
|
484 | } else { | |||
|
485 | elem.setAttribute(k, v); | |||
|
486 | } | |||
|
487 | } | |||
|
488 | } | |||
|
489 | } | |||
|
490 | return elem; | |||
|
491 | }, | |||
|
492 | ||||
|
493 | /** @id MochiKit.DOM.appendChildNodes */ | |||
|
494 | appendChildNodes: function (node/*, nodes...*/) { | |||
|
495 | var elem = node; | |||
|
496 | var self = MochiKit.DOM; | |||
|
497 | if (typeof(node) == 'string') { | |||
|
498 | elem = self.getElement(node); | |||
|
499 | } | |||
|
500 | var nodeStack = [ | |||
|
501 | self.coerceToDOM( | |||
|
502 | MochiKit.Base.extend(null, arguments, 1), | |||
|
503 | elem | |||
|
504 | ) | |||
|
505 | ]; | |||
|
506 | var concat = MochiKit.Base.concat; | |||
|
507 | while (nodeStack.length) { | |||
|
508 | var n = nodeStack.shift(); | |||
|
509 | if (typeof(n) == 'undefined' || n === null) { | |||
|
510 | // pass | |||
|
511 | } else if (typeof(n.nodeType) == 'number') { | |||
|
512 | elem.appendChild(n); | |||
|
513 | } else { | |||
|
514 | nodeStack = concat(n, nodeStack); | |||
|
515 | } | |||
|
516 | } | |||
|
517 | return elem; | |||
|
518 | }, | |||
|
519 | ||||
|
520 | ||||
|
521 | /** @id MochiKit.DOM.insertSiblingNodesBefore */ | |||
|
522 | insertSiblingNodesBefore: function (node/*, nodes...*/) { | |||
|
523 | var elem = node; | |||
|
524 | var self = MochiKit.DOM; | |||
|
525 | if (typeof(node) == 'string') { | |||
|
526 | elem = self.getElement(node); | |||
|
527 | } | |||
|
528 | var nodeStack = [ | |||
|
529 | self.coerceToDOM( | |||
|
530 | MochiKit.Base.extend(null, arguments, 1), | |||
|
531 | elem | |||
|
532 | ) | |||
|
533 | ]; | |||
|
534 | var parentnode = elem.parentNode; | |||
|
535 | var concat = MochiKit.Base.concat; | |||
|
536 | while (nodeStack.length) { | |||
|
537 | var n = nodeStack.shift(); | |||
|
538 | if (typeof(n) == 'undefined' || n === null) { | |||
|
539 | // pass | |||
|
540 | } else if (typeof(n.nodeType) == 'number') { | |||
|
541 | parentnode.insertBefore(n, elem); | |||
|
542 | } else { | |||
|
543 | nodeStack = concat(n, nodeStack); | |||
|
544 | } | |||
|
545 | } | |||
|
546 | return parentnode; | |||
|
547 | }, | |||
|
548 | ||||
|
549 | /** @id MochiKit.DOM.insertSiblingNodesAfter */ | |||
|
550 | insertSiblingNodesAfter: function (node/*, nodes...*/) { | |||
|
551 | var elem = node; | |||
|
552 | var self = MochiKit.DOM; | |||
|
553 | ||||
|
554 | if (typeof(node) == 'string') { | |||
|
555 | elem = self.getElement(node); | |||
|
556 | } | |||
|
557 | var nodeStack = [ | |||
|
558 | self.coerceToDOM( | |||
|
559 | MochiKit.Base.extend(null, arguments, 1), | |||
|
560 | elem | |||
|
561 | ) | |||
|
562 | ]; | |||
|
563 | ||||
|
564 | if (elem.nextSibling) { | |||
|
565 | return self.insertSiblingNodesBefore(elem.nextSibling, nodeStack); | |||
|
566 | } | |||
|
567 | else { | |||
|
568 | return self.appendChildNodes(elem.parentNode, nodeStack); | |||
|
569 | } | |||
|
570 | }, | |||
|
571 | ||||
|
572 | /** @id MochiKit.DOM.replaceChildNodes */ | |||
|
573 | replaceChildNodes: function (node/*, nodes...*/) { | |||
|
574 | var elem = node; | |||
|
575 | var self = MochiKit.DOM; | |||
|
576 | if (typeof(node) == 'string') { | |||
|
577 | elem = self.getElement(node); | |||
|
578 | arguments[0] = elem; | |||
|
579 | } | |||
|
580 | var child; | |||
|
581 | while ((child = elem.firstChild)) { | |||
|
582 | elem.removeChild(child); | |||
|
583 | } | |||
|
584 | if (arguments.length < 2) { | |||
|
585 | return elem; | |||
|
586 | } else { | |||
|
587 | return self.appendChildNodes.apply(this, arguments); | |||
|
588 | } | |||
|
589 | }, | |||
|
590 | ||||
|
591 | /** @id MochiKit.DOM.createDOM */ | |||
|
592 | createDOM: function (name, attrs/*, nodes... */) { | |||
|
593 | var elem; | |||
|
594 | var self = MochiKit.DOM; | |||
|
595 | var m = MochiKit.Base; | |||
|
596 | if (typeof(attrs) == "string" || typeof(attrs) == "number") { | |||
|
597 | var args = m.extend([name, null], arguments, 1); | |||
|
598 | return arguments.callee.apply(this, args); | |||
|
599 | } | |||
|
600 | if (typeof(name) == 'string') { | |||
|
601 | // Internet Explorer is dumb | |||
|
602 | var xhtml = self._xhtml; | |||
|
603 | if (attrs && !self.attributeArray.compliant) { | |||
|
604 | // http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp | |||
|
605 | var contents = ""; | |||
|
606 | if ('name' in attrs) { | |||
|
607 | contents += ' name="' + self.escapeHTML(attrs.name) + '"'; | |||
|
608 | } | |||
|
609 | if (name == 'input' && 'type' in attrs) { | |||
|
610 | contents += ' type="' + self.escapeHTML(attrs.type) + '"'; | |||
|
611 | } | |||
|
612 | if (contents) { | |||
|
613 | name = "<" + name + contents + ">"; | |||
|
614 | xhtml = false; | |||
|
615 | } | |||
|
616 | } | |||
|
617 | var d = self._document; | |||
|
618 | if (xhtml && d === document) { | |||
|
619 | elem = d.createElementNS("http://www.w3.org/1999/xhtml", name); | |||
|
620 | } else { | |||
|
621 | elem = d.createElement(name); | |||
|
622 | } | |||
|
623 | } else { | |||
|
624 | elem = name; | |||
|
625 | } | |||
|
626 | if (attrs) { | |||
|
627 | self.updateNodeAttributes(elem, attrs); | |||
|
628 | } | |||
|
629 | if (arguments.length <= 2) { | |||
|
630 | return elem; | |||
|
631 | } else { | |||
|
632 | var args = m.extend([elem], arguments, 2); | |||
|
633 | return self.appendChildNodes.apply(this, args); | |||
|
634 | } | |||
|
635 | }, | |||
|
636 | ||||
|
637 | /** @id MochiKit.DOM.createDOMFunc */ | |||
|
638 | createDOMFunc: function (/* tag, attrs, *nodes */) { | |||
|
639 | var m = MochiKit.Base; | |||
|
640 | return m.partial.apply( | |||
|
641 | this, | |||
|
642 | m.extend([MochiKit.DOM.createDOM], arguments) | |||
|
643 | ); | |||
|
644 | }, | |||
|
645 | ||||
|
646 | /** @id MochiKit.DOM.removeElement */ | |||
|
647 | removeElement: function (elem) { | |||
|
648 | var e = MochiKit.DOM.getElement(elem); | |||
|
649 | e.parentNode.removeChild(e); | |||
|
650 | return e; | |||
|
651 | }, | |||
|
652 | ||||
|
653 | /** @id MochiKit.DOM.swapDOM */ | |||
|
654 | swapDOM: function (dest, src) { | |||
|
655 | var self = MochiKit.DOM; | |||
|
656 | dest = self.getElement(dest); | |||
|
657 | var parent = dest.parentNode; | |||
|
658 | if (src) { | |||
|
659 | src = self.getElement(src); | |||
|
660 | parent.replaceChild(src, dest); | |||
|
661 | } else { | |||
|
662 | parent.removeChild(dest); | |||
|
663 | } | |||
|
664 | return src; | |||
|
665 | }, | |||
|
666 | ||||
|
667 | /** @id MochiKit.DOM.getElement */ | |||
|
668 | getElement: function (id) { | |||
|
669 | var self = MochiKit.DOM; | |||
|
670 | if (arguments.length == 1) { | |||
|
671 | return ((typeof(id) == "string") ? | |||
|
672 | self._document.getElementById(id) : id); | |||
|
673 | } else { | |||
|
674 | return MochiKit.Base.map(self.getElement, arguments); | |||
|
675 | } | |||
|
676 | }, | |||
|
677 | ||||
|
678 | /** @id MochiKit.DOM.getElementsByTagAndClassName */ | |||
|
679 | getElementsByTagAndClassName: function (tagName, className, | |||
|
680 | /* optional */parent) { | |||
|
681 | var self = MochiKit.DOM; | |||
|
682 | if (typeof(tagName) == 'undefined' || tagName === null) { | |||
|
683 | tagName = '*'; | |||
|
684 | } | |||
|
685 | if (typeof(parent) == 'undefined' || parent === null) { | |||
|
686 | parent = self._document; | |||
|
687 | } | |||
|
688 | parent = self.getElement(parent); | |||
|
689 | var children = (parent.getElementsByTagName(tagName) | |||
|
690 | || self._document.all); | |||
|
691 | if (typeof(className) == 'undefined' || className === null) { | |||
|
692 | return MochiKit.Base.extend(null, children); | |||
|
693 | } | |||
|
694 | ||||
|
695 | var elements = []; | |||
|
696 | for (var i = 0; i < children.length; i++) { | |||
|
697 | var child = children[i]; | |||
|
698 | var cls = child.className; | |||
|
699 | if (!cls) { | |||
|
700 | continue; | |||
|
701 | } | |||
|
702 | var classNames = cls.split(' '); | |||
|
703 | for (var j = 0; j < classNames.length; j++) { | |||
|
704 | if (classNames[j] == className) { | |||
|
705 | elements.push(child); | |||
|
706 | break; | |||
|
707 | } | |||
|
708 | } | |||
|
709 | } | |||
|
710 | ||||
|
711 | return elements; | |||
|
712 | }, | |||
|
713 | ||||
|
714 | _newCallStack: function (path, once) { | |||
|
715 | var rval = function () { | |||
|
716 | var callStack = arguments.callee.callStack; | |||
|
717 | for (var i = 0; i < callStack.length; i++) { | |||
|
718 | if (callStack[i].apply(this, arguments) === false) { | |||
|
719 | break; | |||
|
720 | } | |||
|
721 | } | |||
|
722 | if (once) { | |||
|
723 | try { | |||
|
724 | this[path] = null; | |||
|
725 | } catch (e) { | |||
|
726 | // pass | |||
|
727 | } | |||
|
728 | } | |||
|
729 | }; | |||
|
730 | rval.callStack = []; | |||
|
731 | return rval; | |||
|
732 | }, | |||
|
733 | ||||
|
734 | /** @id MochiKit.DOM.addToCallStack */ | |||
|
735 | addToCallStack: function (target, path, func, once) { | |||
|
736 | var self = MochiKit.DOM; | |||
|
737 | var existing = target[path]; | |||
|
738 | var regfunc = existing; | |||
|
739 | if (!(typeof(existing) == 'function' | |||
|
740 | && typeof(existing.callStack) == "object" | |||
|
741 | && existing.callStack !== null)) { | |||
|
742 | regfunc = self._newCallStack(path, once); | |||
|
743 | if (typeof(existing) == 'function') { | |||
|
744 | regfunc.callStack.push(existing); | |||
|
745 | } | |||
|
746 | target[path] = regfunc; | |||
|
747 | } | |||
|
748 | regfunc.callStack.push(func); | |||
|
749 | }, | |||
|
750 | ||||
|
751 | /** @id MochiKit.DOM.addLoadEvent */ | |||
|
752 | addLoadEvent: function (func) { | |||
|
753 | var self = MochiKit.DOM; | |||
|
754 | self.addToCallStack(self._window, "onload", func, true); | |||
|
755 | ||||
|
756 | }, | |||
|
757 | ||||
|
758 | /** @id MochiKit.DOM.focusOnLoad */ | |||
|
759 | focusOnLoad: function (element) { | |||
|
760 | var self = MochiKit.DOM; | |||
|
761 | self.addLoadEvent(function () { | |||
|
762 | element = self.getElement(element); | |||
|
763 | if (element) { | |||
|
764 | element.focus(); | |||
|
765 | } | |||
|
766 | }); | |||
|
767 | }, | |||
|
768 | ||||
|
769 | /** @id MochiKit.DOM.setElementClass */ | |||
|
770 | setElementClass: function (element, className) { | |||
|
771 | var self = MochiKit.DOM; | |||
|
772 | var obj = self.getElement(element); | |||
|
773 | if (self.attributeArray.compliant) { | |||
|
774 | obj.setAttribute("class", className); | |||
|
775 | } else { | |||
|
776 | obj.setAttribute("className", className); | |||
|
777 | } | |||
|
778 | }, | |||
|
779 | ||||
|
780 | /** @id MochiKit.DOM.toggleElementClass */ | |||
|
781 | toggleElementClass: function (className/*, element... */) { | |||
|
782 | var self = MochiKit.DOM; | |||
|
783 | for (var i = 1; i < arguments.length; i++) { | |||
|
784 | var obj = self.getElement(arguments[i]); | |||
|
785 | if (!self.addElementClass(obj, className)) { | |||
|
786 | self.removeElementClass(obj, className); | |||
|
787 | } | |||
|
788 | } | |||
|
789 | }, | |||
|
790 | ||||
|
791 | /** @id MochiKit.DOM.addElementClass */ | |||
|
792 | addElementClass: function (element, className) { | |||
|
793 | var self = MochiKit.DOM; | |||
|
794 | var obj = self.getElement(element); | |||
|
795 | var cls = obj.className; | |||
|
796 | // trivial case, no className yet | |||
|
797 | if (cls == undefined || cls.length === 0) { | |||
|
798 | self.setElementClass(obj, className); | |||
|
799 | return true; | |||
|
800 | } | |||
|
801 | // the other trivial case, already set as the only class | |||
|
802 | if (cls == className) { | |||
|
803 | return false; | |||
|
804 | } | |||
|
805 | var classes = cls.split(" "); | |||
|
806 | for (var i = 0; i < classes.length; i++) { | |||
|
807 | // already present | |||
|
808 | if (classes[i] == className) { | |||
|
809 | return false; | |||
|
810 | } | |||
|
811 | } | |||
|
812 | // append class | |||
|
813 | self.setElementClass(obj, cls + " " + className); | |||
|
814 | return true; | |||
|
815 | }, | |||
|
816 | ||||
|
817 | /** @id MochiKit.DOM.removeElementClass */ | |||
|
818 | removeElementClass: function (element, className) { | |||
|
819 | var self = MochiKit.DOM; | |||
|
820 | var obj = self.getElement(element); | |||
|
821 | var cls = obj.className; | |||
|
822 | // trivial case, no className yet | |||
|
823 | if (cls == undefined || cls.length === 0) { | |||
|
824 | return false; | |||
|
825 | } | |||
|
826 | // other trivial case, set only to className | |||
|
827 | if (cls == className) { | |||
|
828 | self.setElementClass(obj, ""); | |||
|
829 | return true; | |||
|
830 | } | |||
|
831 | var classes = cls.split(" "); | |||
|
832 | for (var i = 0; i < classes.length; i++) { | |||
|
833 | // already present | |||
|
834 | if (classes[i] == className) { | |||
|
835 | // only check sane case where the class is used once | |||
|
836 | classes.splice(i, 1); | |||
|
837 | self.setElementClass(obj, classes.join(" ")); | |||
|
838 | return true; | |||
|
839 | } | |||
|
840 | } | |||
|
841 | // not found | |||
|
842 | return false; | |||
|
843 | }, | |||
|
844 | ||||
|
845 | /** @id MochiKit.DOM.swapElementClass */ | |||
|
846 | swapElementClass: function (element, fromClass, toClass) { | |||
|
847 | var obj = MochiKit.DOM.getElement(element); | |||
|
848 | var res = MochiKit.DOM.removeElementClass(obj, fromClass); | |||
|
849 | if (res) { | |||
|
850 | MochiKit.DOM.addElementClass(obj, toClass); | |||
|
851 | } | |||
|
852 | return res; | |||
|
853 | }, | |||
|
854 | ||||
|
855 | /** @id MochiKit.DOM.hasElementClass */ | |||
|
856 | hasElementClass: function (element, className/*...*/) { | |||
|
857 | var obj = MochiKit.DOM.getElement(element); | |||
|
858 | var cls = obj.className; | |||
|
859 | if (!cls) { | |||
|
860 | return false; | |||
|
861 | } | |||
|
862 | var classes = cls.split(" "); | |||
|
863 | for (var i = 1; i < arguments.length; i++) { | |||
|
864 | var good = false; | |||
|
865 | for (var j = 0; j < classes.length; j++) { | |||
|
866 | if (classes[j] == arguments[i]) { | |||
|
867 | good = true; | |||
|
868 | break; | |||
|
869 | } | |||
|
870 | } | |||
|
871 | if (!good) { | |||
|
872 | return false; | |||
|
873 | } | |||
|
874 | } | |||
|
875 | return true; | |||
|
876 | }, | |||
|
877 | ||||
|
878 | /** @id MochiKit.DOM.escapeHTML */ | |||
|
879 | escapeHTML: function (s) { | |||
|
880 | return s.replace(/&/g, "&" | |||
|
881 | ).replace(/"/g, """ | |||
|
882 | ).replace(/</g, "<" | |||
|
883 | ).replace(/>/g, ">"); | |||
|
884 | }, | |||
|
885 | ||||
|
886 | /** @id MochiKit.DOM.toHTML */ | |||
|
887 | toHTML: function (dom) { | |||
|
888 | return MochiKit.DOM.emitHTML(dom).join(""); | |||
|
889 | }, | |||
|
890 | ||||
|
891 | /** @id MochiKit.DOM.emitHTML */ | |||
|
892 | emitHTML: function (dom, /* optional */lst) { | |||
|
893 | if (typeof(lst) == 'undefined' || lst === null) { | |||
|
894 | lst = []; | |||
|
895 | } | |||
|
896 | // queue is the call stack, we're doing this non-recursively | |||
|
897 | var queue = [dom]; | |||
|
898 | var self = MochiKit.DOM; | |||
|
899 | var escapeHTML = self.escapeHTML; | |||
|
900 | var attributeArray = self.attributeArray; | |||
|
901 | while (queue.length) { | |||
|
902 | dom = queue.pop(); | |||
|
903 | if (typeof(dom) == 'string') { | |||
|
904 | lst.push(dom); | |||
|
905 | } else if (dom.nodeType == 1) { | |||
|
906 | // we're not using higher order stuff here | |||
|
907 | // because safari has heisenbugs.. argh. | |||
|
908 | // | |||
|
909 | // I think it might have something to do with | |||
|
910 | // garbage collection and function calls. | |||
|
911 | lst.push('<' + dom.tagName.toLowerCase()); | |||
|
912 | var attributes = []; | |||
|
913 | var domAttr = attributeArray(dom); | |||
|
914 | for (var i = 0; i < domAttr.length; i++) { | |||
|
915 | var a = domAttr[i]; | |||
|
916 | attributes.push([ | |||
|
917 | " ", | |||
|
918 | a.name, | |||
|
919 | '="', | |||
|
920 | escapeHTML(a.value), | |||
|
921 | '"' | |||
|
922 | ]); | |||
|
923 | } | |||
|
924 | attributes.sort(); | |||
|
925 | for (i = 0; i < attributes.length; i++) { | |||
|
926 | var attrs = attributes[i]; | |||
|
927 | for (var j = 0; j < attrs.length; j++) { | |||
|
928 | lst.push(attrs[j]); | |||
|
929 | } | |||
|
930 | } | |||
|
931 | if (dom.hasChildNodes()) { | |||
|
932 | lst.push(">"); | |||
|
933 | // queue is the FILO call stack, so we put the close tag | |||
|
934 | // on first | |||
|
935 | queue.push("</" + dom.tagName.toLowerCase() + ">"); | |||
|
936 | var cnodes = dom.childNodes; | |||
|
937 | for (i = cnodes.length - 1; i >= 0; i--) { | |||
|
938 | queue.push(cnodes[i]); | |||
|
939 | } | |||
|
940 | } else { | |||
|
941 | lst.push('/>'); | |||
|
942 | } | |||
|
943 | } else if (dom.nodeType == 3) { | |||
|
944 | lst.push(escapeHTML(dom.nodeValue)); | |||
|
945 | } | |||
|
946 | } | |||
|
947 | return lst; | |||
|
948 | }, | |||
|
949 | ||||
|
950 | /** @id MochiKit.DOM.scrapeText */ | |||
|
951 | scrapeText: function (node, /* optional */asArray) { | |||
|
952 | var rval = []; | |||
|
953 | (function (node) { | |||
|
954 | var cn = node.childNodes; | |||
|
955 | if (cn) { | |||
|
956 | for (var i = 0; i < cn.length; i++) { | |||
|
957 | arguments.callee.call(this, cn[i]); | |||
|
958 | } | |||
|
959 | } | |||
|
960 | var nodeValue = node.nodeValue; | |||
|
961 | if (typeof(nodeValue) == 'string') { | |||
|
962 | rval.push(nodeValue); | |||
|
963 | } | |||
|
964 | })(MochiKit.DOM.getElement(node)); | |||
|
965 | if (asArray) { | |||
|
966 | return rval; | |||
|
967 | } else { | |||
|
968 | return rval.join(""); | |||
|
969 | } | |||
|
970 | }, | |||
|
971 | ||||
|
972 | /** @id MochiKit.DOM.removeEmptyTextNodes */ | |||
|
973 | removeEmptyTextNodes: function (element) { | |||
|
974 | element = MochiKit.DOM.getElement(element); | |||
|
975 | for (var i = 0; i < element.childNodes.length; i++) { | |||
|
976 | var node = element.childNodes[i]; | |||
|
977 | if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) { | |||
|
978 | node.parentNode.removeChild(node); | |||
|
979 | } | |||
|
980 | } | |||
|
981 | }, | |||
|
982 | ||||
|
983 | /** @id MochiKit.DOM.makeClipping */ | |||
|
984 | makeClipping: function (element) { | |||
|
985 | element = MochiKit.DOM.getElement(element); | |||
|
986 | var oldOverflow = element.style.overflow; | |||
|
987 | if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') { | |||
|
988 | element.style.overflow = 'hidden'; | |||
|
989 | } | |||
|
990 | return oldOverflow; | |||
|
991 | }, | |||
|
992 | ||||
|
993 | /** @id MochiKit.DOM.undoClipping */ | |||
|
994 | undoClipping: function (element, overflow) { | |||
|
995 | element = MochiKit.DOM.getElement(element); | |||
|
996 | if (!overflow) { | |||
|
997 | return; | |||
|
998 | } | |||
|
999 | element.style.overflow = overflow; | |||
|
1000 | }, | |||
|
1001 | ||||
|
1002 | /** @id MochiKit.DOM.makePositioned */ | |||
|
1003 | makePositioned: function (element) { | |||
|
1004 | element = MochiKit.DOM.getElement(element); | |||
|
1005 | var pos = MochiKit.Style.getStyle(element, 'position'); | |||
|
1006 | if (pos == 'static' || !pos) { | |||
|
1007 | element.style.position = 'relative'; | |||
|
1008 | // Opera returns the offset relative to the positioning context, | |||
|
1009 | // when an element is position relative but top and left have | |||
|
1010 | // not been defined | |||
|
1011 | if (/Opera/.test(navigator.userAgent)) { | |||
|
1012 | element.style.top = 0; | |||
|
1013 | element.style.left = 0; | |||
|
1014 | } | |||
|
1015 | } | |||
|
1016 | }, | |||
|
1017 | ||||
|
1018 | /** @id MochiKit.DOM.undoPositioned */ | |||
|
1019 | undoPositioned: function (element) { | |||
|
1020 | element = MochiKit.DOM.getElement(element); | |||
|
1021 | if (element.style.position == 'relative') { | |||
|
1022 | element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = ''; | |||
|
1023 | } | |||
|
1024 | }, | |||
|
1025 | ||||
|
1026 | /** @id MochiKit.DOM.getFirstElementByTagAndClassName */ | |||
|
1027 | getFirstElementByTagAndClassName: function (tagName, className, | |||
|
1028 | /* optional */parent) { | |||
|
1029 | var self = MochiKit.DOM; | |||
|
1030 | if (typeof(tagName) == 'undefined' || tagName === null) { | |||
|
1031 | tagName = '*'; | |||
|
1032 | } | |||
|
1033 | if (typeof(parent) == 'undefined' || parent === null) { | |||
|
1034 | parent = self._document; | |||
|
1035 | } | |||
|
1036 | parent = self.getElement(parent); | |||
|
1037 | var children = (parent.getElementsByTagName(tagName) | |||
|
1038 | || self._document.all); | |||
|
1039 | if (typeof(className) == 'undefined' || className === null) { | |||
|
1040 | return children[0]; | |||
|
1041 | } | |||
|
1042 | ||||
|
1043 | for (var i = 0; i < children.length; i++) { | |||
|
1044 | var child = children[i]; | |||
|
1045 | var classNames = child.className.split(' '); | |||
|
1046 | for (var j = 0; j < classNames.length; j++) { | |||
|
1047 | if (classNames[j] == className) { | |||
|
1048 | return child; | |||
|
1049 | } | |||
|
1050 | } | |||
|
1051 | } | |||
|
1052 | }, | |||
|
1053 | ||||
|
1054 | /** @id MochiKit.DOM.getFirstParentByTagAndClassName */ | |||
|
1055 | getFirstParentByTagAndClassName: function (elem, tagName, className) { | |||
|
1056 | var self = MochiKit.DOM; | |||
|
1057 | elem = self.getElement(elem); | |||
|
1058 | if (typeof(tagName) == 'undefined' || tagName === null) { | |||
|
1059 | tagName = '*'; | |||
|
1060 | } else { | |||
|
1061 | tagName = tagName.toUpperCase(); | |||
|
1062 | } | |||
|
1063 | if (typeof(className) == 'undefined' || className === null) { | |||
|
1064 | className = null; | |||
|
1065 | } | |||
|
1066 | ||||
|
1067 | var classList = ''; | |||
|
1068 | var curTagName = ''; | |||
|
1069 | while (elem && elem.tagName) { | |||
|
1070 | elem = elem.parentNode; | |||
|
1071 | if (tagName == '*' && className === null) { | |||
|
1072 | return elem; | |||
|
1073 | } | |||
|
1074 | classList = elem.className.split(' '); | |||
|
1075 | curTagName = elem.tagName.toUpperCase(); | |||
|
1076 | if (className === null && tagName == curTagName) { | |||
|
1077 | return elem; | |||
|
1078 | } else if (className !== null) { | |||
|
1079 | for (var i = 0; i < classList.length; i++) { | |||
|
1080 | if (tagName == '*' && classList[i] == className) { | |||
|
1081 | return elem; | |||
|
1082 | } else if (tagName == curTagName && classList[i] == className) { | |||
|
1083 | return elem; | |||
|
1084 | } | |||
|
1085 | } | |||
|
1086 | } | |||
|
1087 | } | |||
|
1088 | return elem; | |||
|
1089 | }, | |||
|
1090 | ||||
|
1091 | /** @id MochiKit.DOM.isParent */ | |||
|
1092 | isParent: function (child, element) { | |||
|
1093 | if (!child.parentNode || child == element) { | |||
|
1094 | return false; | |||
|
1095 | } | |||
|
1096 | ||||
|
1097 | if (child.parentNode == element) { | |||
|
1098 | return true; | |||
|
1099 | } | |||
|
1100 | ||||
|
1101 | return MochiKit.DOM.isParent(child.parentNode, element); | |||
|
1102 | }, | |||
|
1103 | ||||
|
1104 | __new__: function (win) { | |||
|
1105 | ||||
|
1106 | var m = MochiKit.Base; | |||
|
1107 | if (typeof(document) != "undefined") { | |||
|
1108 | this._document = document; | |||
|
1109 | var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; | |||
|
1110 | this._xhtml = (document.documentElement && | |||
|
1111 | document.createElementNS && | |||
|
1112 | document.documentElement.namespaceURI === kXULNSURI); | |||
|
1113 | } else if (MochiKit.MockDOM) { | |||
|
1114 | this._document = MochiKit.MockDOM.document; | |||
|
1115 | } | |||
|
1116 | this._window = win; | |||
|
1117 | ||||
|
1118 | this.domConverters = new m.AdapterRegistry(); | |||
|
1119 | ||||
|
1120 | var __tmpElement = this._document.createElement("span"); | |||
|
1121 | var attributeArray; | |||
|
1122 | if (__tmpElement && __tmpElement.attributes && | |||
|
1123 | __tmpElement.attributes.length > 0) { | |||
|
1124 | // for braindead browsers (IE) that insert extra junk | |||
|
1125 | var filter = m.filter; | |||
|
1126 | attributeArray = function (node) { | |||
|
1127 | return filter(attributeArray.ignoreAttrFilter, node.attributes); | |||
|
1128 | }; | |||
|
1129 | attributeArray.ignoreAttr = {}; | |||
|
1130 | var attrs = __tmpElement.attributes; | |||
|
1131 | var ignoreAttr = attributeArray.ignoreAttr; | |||
|
1132 | for (var i = 0; i < attrs.length; i++) { | |||
|
1133 | var a = attrs[i]; | |||
|
1134 | ignoreAttr[a.name] = a.value; | |||
|
1135 | } | |||
|
1136 | attributeArray.ignoreAttrFilter = function (a) { | |||
|
1137 | return (attributeArray.ignoreAttr[a.name] != a.value); | |||
|
1138 | }; | |||
|
1139 | attributeArray.compliant = false; | |||
|
1140 | attributeArray.renames = { | |||
|
1141 | "class": "className", | |||
|
1142 | "checked": "defaultChecked", | |||
|
1143 | "usemap": "useMap", | |||
|
1144 | "for": "htmlFor", | |||
|
1145 | "readonly": "readOnly", | |||
|
1146 | "colspan": "colSpan", | |||
|
1147 | "bgcolor": "bgColor", | |||
|
1148 | "cellspacing": "cellSpacing", | |||
|
1149 | "cellpadding": "cellPadding" | |||
|
1150 | }; | |||
|
1151 | } else { | |||
|
1152 | attributeArray = function (node) { | |||
|
1153 | /*** | |||
|
1154 | ||||
|
1155 | Return an array of attributes for a given node, | |||
|
1156 | filtering out attributes that don't belong for | |||
|
1157 | that are inserted by "Certain Browsers". | |||
|
1158 | ||||
|
1159 | ***/ | |||
|
1160 | return node.attributes; | |||
|
1161 | }; | |||
|
1162 | attributeArray.compliant = true; | |||
|
1163 | attributeArray.renames = {}; | |||
|
1164 | } | |||
|
1165 | this.attributeArray = attributeArray; | |||
|
1166 | ||||
|
1167 | // FIXME: this really belongs in Base, and could probably be cleaner | |||
|
1168 | var _deprecated = function(fromModule, arr) { | |||
|
1169 | var modules = arr[1].split('.'); | |||
|
1170 | var str = ''; | |||
|
1171 | var obj = {}; | |||
|
1172 | ||||
|
1173 | str += 'if (!MochiKit.' + modules[1] + ') { throw new Error("'; | |||
|
1174 | str += 'This function has been deprecated and depends on MochiKit.'; | |||
|
1175 | str += modules[1] + '.");}'; | |||
|
1176 | str += 'return MochiKit.' + modules[1] + '.' + arr[0]; | |||
|
1177 | str += '.apply(this, arguments);'; | |||
|
1178 | ||||
|
1179 | obj[modules[2]] = new Function(str); | |||
|
1180 | MochiKit.Base.update(MochiKit[fromModule], obj); | |||
|
1181 | } | |||
|
1182 | for (var i; i < MochiKit.DOM.DEPRECATED.length; i++) { | |||
|
1183 | _deprecated('DOM', MochiKit.DOM.DEPRECATED[i]); | |||
|
1184 | } | |||
|
1185 | ||||
|
1186 | // shorthand for createDOM syntax | |||
|
1187 | var createDOMFunc = this.createDOMFunc; | |||
|
1188 | /** @id MochiKit.DOM.UL */ | |||
|
1189 | this.UL = createDOMFunc("ul"); | |||
|
1190 | /** @id MochiKit.DOM.OL */ | |||
|
1191 | this.OL = createDOMFunc("ol"); | |||
|
1192 | /** @id MochiKit.DOM.LI */ | |||
|
1193 | this.LI = createDOMFunc("li"); | |||
|
1194 | /** @id MochiKit.DOM.TD */ | |||
|
1195 | this.TD = createDOMFunc("td"); | |||
|
1196 | /** @id MochiKit.DOM.TR */ | |||
|
1197 | this.TR = createDOMFunc("tr"); | |||
|
1198 | /** @id MochiKit.DOM.TBODY */ | |||
|
1199 | this.TBODY = createDOMFunc("tbody"); | |||
|
1200 | /** @id MochiKit.DOM.THEAD */ | |||
|
1201 | this.THEAD = createDOMFunc("thead"); | |||
|
1202 | /** @id MochiKit.DOM.TFOOT */ | |||
|
1203 | this.TFOOT = createDOMFunc("tfoot"); | |||
|
1204 | /** @id MochiKit.DOM.TABLE */ | |||
|
1205 | this.TABLE = createDOMFunc("table"); | |||
|
1206 | /** @id MochiKit.DOM.TH */ | |||
|
1207 | this.TH = createDOMFunc("th"); | |||
|
1208 | /** @id MochiKit.DOM.INPUT */ | |||
|
1209 | this.INPUT = createDOMFunc("input"); | |||
|
1210 | /** @id MochiKit.DOM.SPAN */ | |||
|
1211 | this.SPAN = createDOMFunc("span"); | |||
|
1212 | /** @id MochiKit.DOM.A */ | |||
|
1213 | this.A = createDOMFunc("a"); | |||
|
1214 | /** @id MochiKit.DOM.DIV */ | |||
|
1215 | this.DIV = createDOMFunc("div"); | |||
|
1216 | /** @id MochiKit.DOM.IMG */ | |||
|
1217 | this.IMG = createDOMFunc("img"); | |||
|
1218 | /** @id MochiKit.DOM.BUTTON */ | |||
|
1219 | this.BUTTON = createDOMFunc("button"); | |||
|
1220 | /** @id MochiKit.DOM.TT */ | |||
|
1221 | this.TT = createDOMFunc("tt"); | |||
|
1222 | /** @id MochiKit.DOM.PRE */ | |||
|
1223 | this.PRE = createDOMFunc("pre"); | |||
|
1224 | /** @id MochiKit.DOM.H1 */ | |||
|
1225 | this.H1 = createDOMFunc("h1"); | |||
|
1226 | /** @id MochiKit.DOM.H2 */ | |||
|
1227 | this.H2 = createDOMFunc("h2"); | |||
|
1228 | /** @id MochiKit.DOM.H3 */ | |||
|
1229 | this.H3 = createDOMFunc("h3"); | |||
|
1230 | /** @id MochiKit.DOM.BR */ | |||
|
1231 | this.BR = createDOMFunc("br"); | |||
|
1232 | /** @id MochiKit.DOM.HR */ | |||
|
1233 | this.HR = createDOMFunc("hr"); | |||
|
1234 | /** @id MochiKit.DOM.LABEL */ | |||
|
1235 | this.LABEL = createDOMFunc("label"); | |||
|
1236 | /** @id MochiKit.DOM.TEXTAREA */ | |||
|
1237 | this.TEXTAREA = createDOMFunc("textarea"); | |||
|
1238 | /** @id MochiKit.DOM.FORM */ | |||
|
1239 | this.FORM = createDOMFunc("form"); | |||
|
1240 | /** @id MochiKit.DOM.P */ | |||
|
1241 | this.P = createDOMFunc("p"); | |||
|
1242 | /** @id MochiKit.DOM.SELECT */ | |||
|
1243 | this.SELECT = createDOMFunc("select"); | |||
|
1244 | /** @id MochiKit.DOM.OPTION */ | |||
|
1245 | this.OPTION = createDOMFunc("option"); | |||
|
1246 | /** @id MochiKit.DOM.OPTGROUP */ | |||
|
1247 | this.OPTGROUP = createDOMFunc("optgroup"); | |||
|
1248 | /** @id MochiKit.DOM.LEGEND */ | |||
|
1249 | this.LEGEND = createDOMFunc("legend"); | |||
|
1250 | /** @id MochiKit.DOM.FIELDSET */ | |||
|
1251 | this.FIELDSET = createDOMFunc("fieldset"); | |||
|
1252 | /** @id MochiKit.DOM.STRONG */ | |||
|
1253 | this.STRONG = createDOMFunc("strong"); | |||
|
1254 | /** @id MochiKit.DOM.CANVAS */ | |||
|
1255 | this.CANVAS = createDOMFunc("canvas"); | |||
|
1256 | ||||
|
1257 | /** @id MochiKit.DOM.$ */ | |||
|
1258 | this.$ = this.getElement; | |||
|
1259 | ||||
|
1260 | this.EXPORT_TAGS = { | |||
|
1261 | ":common": this.EXPORT, | |||
|
1262 | ":all": m.concat(this.EXPORT, this.EXPORT_OK) | |||
|
1263 | }; | |||
|
1264 | ||||
|
1265 | m.nameFunctions(this); | |||
|
1266 | ||||
|
1267 | } | |||
|
1268 | }); | |||
|
1269 | ||||
|
1270 | ||||
|
1271 | MochiKit.DOM.__new__(((typeof(window) == "undefined") ? this : window)); | |||
|
1272 | ||||
|
1273 | // | |||
|
1274 | // XXX: Internet Explorer blows | |||
|
1275 | // | |||
|
1276 | if (MochiKit.__export__) { | |||
|
1277 | withWindow = MochiKit.DOM.withWindow; | |||
|
1278 | withDocument = MochiKit.DOM.withDocument; | |||
|
1279 | } | |||
|
1280 | ||||
|
1281 | MochiKit.Base._exportSymbols(this, MochiKit.DOM); |
@@ -0,0 +1,216 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.DateTime 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.DateTime'); | |||
|
13 | } | |||
|
14 | ||||
|
15 | if (typeof(MochiKit) == 'undefined') { | |||
|
16 | MochiKit = {}; | |||
|
17 | } | |||
|
18 | ||||
|
19 | if (typeof(MochiKit.DateTime) == 'undefined') { | |||
|
20 | MochiKit.DateTime = {}; | |||
|
21 | } | |||
|
22 | ||||
|
23 | MochiKit.DateTime.NAME = "MochiKit.DateTime"; | |||
|
24 | MochiKit.DateTime.VERSION = "1.4"; | |||
|
25 | MochiKit.DateTime.__repr__ = function () { | |||
|
26 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
27 | }; | |||
|
28 | MochiKit.DateTime.toString = function () { | |||
|
29 | return this.__repr__(); | |||
|
30 | }; | |||
|
31 | ||||
|
32 | /** @id MochiKit.DateTime.isoDate */ | |||
|
33 | MochiKit.DateTime.isoDate = function (str) { | |||
|
34 | str = str + ""; | |||
|
35 | if (typeof(str) != "string" || str.length === 0) { | |||
|
36 | return null; | |||
|
37 | } | |||
|
38 | var iso = str.split('-'); | |||
|
39 | if (iso.length === 0) { | |||
|
40 | return null; | |||
|
41 | } | |||
|
42 | return new Date(iso[0], iso[1] - 1, iso[2]); | |||
|
43 | }; | |||
|
44 | ||||
|
45 | MochiKit.DateTime._isoRegexp = /(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/; | |||
|
46 | ||||
|
47 | /** @id MochiKit.DateTime.isoTimestamp */ | |||
|
48 | MochiKit.DateTime.isoTimestamp = function (str) { | |||
|
49 | str = str + ""; | |||
|
50 | if (typeof(str) != "string" || str.length === 0) { | |||
|
51 | return null; | |||
|
52 | } | |||
|
53 | var res = str.match(MochiKit.DateTime._isoRegexp); | |||
|
54 | if (typeof(res) == "undefined" || res === null) { | |||
|
55 | return null; | |||
|
56 | } | |||
|
57 | var year, month, day, hour, min, sec, msec; | |||
|
58 | year = parseInt(res[1], 10); | |||
|
59 | if (typeof(res[2]) == "undefined" || res[2] === '') { | |||
|
60 | return new Date(year); | |||
|
61 | } | |||
|
62 | month = parseInt(res[2], 10) - 1; | |||
|
63 | day = parseInt(res[3], 10); | |||
|
64 | if (typeof(res[4]) == "undefined" || res[4] === '') { | |||
|
65 | return new Date(year, month, day); | |||
|
66 | } | |||
|
67 | hour = parseInt(res[4], 10); | |||
|
68 | min = parseInt(res[5], 10); | |||
|
69 | sec = (typeof(res[6]) != "undefined" && res[6] !== '') ? parseInt(res[6], 10) : 0; | |||
|
70 | if (typeof(res[7]) != "undefined" && res[7] !== '') { | |||
|
71 | msec = Math.round(1000.0 * parseFloat("0." + res[7])); | |||
|
72 | } else { | |||
|
73 | msec = 0; | |||
|
74 | } | |||
|
75 | if ((typeof(res[8]) == "undefined" || res[8] === '') && (typeof(res[9]) == "undefined" || res[9] === '')) { | |||
|
76 | return new Date(year, month, day, hour, min, sec, msec); | |||
|
77 | } | |||
|
78 | var ofs; | |||
|
79 | if (typeof(res[9]) != "undefined" && res[9] !== '') { | |||
|
80 | ofs = parseInt(res[10], 10) * 3600000; | |||
|
81 | if (typeof(res[11]) != "undefined" && res[11] !== '') { | |||
|
82 | ofs += parseInt(res[11], 10) * 60000; | |||
|
83 | } | |||
|
84 | if (res[9] == "-") { | |||
|
85 | ofs = -ofs; | |||
|
86 | } | |||
|
87 | } else { | |||
|
88 | ofs = 0; | |||
|
89 | } | |||
|
90 | return new Date(Date.UTC(year, month, day, hour, min, sec, msec) - ofs); | |||
|
91 | }; | |||
|
92 | ||||
|
93 | /** @id MochiKit.DateTime.toISOTime */ | |||
|
94 | MochiKit.DateTime.toISOTime = function (date, realISO/* = false */) { | |||
|
95 | if (typeof(date) == "undefined" || date === null) { | |||
|
96 | return null; | |||
|
97 | } | |||
|
98 | var hh = date.getHours(); | |||
|
99 | var mm = date.getMinutes(); | |||
|
100 | var ss = date.getSeconds(); | |||
|
101 | var lst = [ | |||
|
102 | ((realISO && (hh < 10)) ? "0" + hh : hh), | |||
|
103 | ((mm < 10) ? "0" + mm : mm), | |||
|
104 | ((ss < 10) ? "0" + ss : ss) | |||
|
105 | ]; | |||
|
106 | return lst.join(":"); | |||
|
107 | }; | |||
|
108 | ||||
|
109 | /** @id MochiKit.DateTime.toISOTimeStamp */ | |||
|
110 | MochiKit.DateTime.toISOTimestamp = function (date, realISO/* = false*/) { | |||
|
111 | if (typeof(date) == "undefined" || date === null) { | |||
|
112 | return null; | |||
|
113 | } | |||
|
114 | var sep = realISO ? "T" : " "; | |||
|
115 | var foot = realISO ? "Z" : ""; | |||
|
116 | if (realISO) { | |||
|
117 | date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000)); | |||
|
118 | } | |||
|
119 | return MochiKit.DateTime.toISODate(date) + sep + MochiKit.DateTime.toISOTime(date, realISO) + foot; | |||
|
120 | }; | |||
|
121 | ||||
|
122 | /** @id MochiKit.DateTime.toISODate */ | |||
|
123 | MochiKit.DateTime.toISODate = function (date) { | |||
|
124 | if (typeof(date) == "undefined" || date === null) { | |||
|
125 | return null; | |||
|
126 | } | |||
|
127 | var _padTwo = MochiKit.DateTime._padTwo; | |||
|
128 | return [ | |||
|
129 | date.getFullYear(), | |||
|
130 | _padTwo(date.getMonth() + 1), | |||
|
131 | _padTwo(date.getDate()) | |||
|
132 | ].join("-"); | |||
|
133 | }; | |||
|
134 | ||||
|
135 | /** @id MochiKit.DateTime.americanDate */ | |||
|
136 | MochiKit.DateTime.americanDate = function (d) { | |||
|
137 | d = d + ""; | |||
|
138 | if (typeof(d) != "string" || d.length === 0) { | |||
|
139 | return null; | |||
|
140 | } | |||
|
141 | var a = d.split('/'); | |||
|
142 | return new Date(a[2], a[0] - 1, a[1]); | |||
|
143 | }; | |||
|
144 | ||||
|
145 | MochiKit.DateTime._padTwo = function (n) { | |||
|
146 | return (n > 9) ? n : "0" + n; | |||
|
147 | }; | |||
|
148 | ||||
|
149 | /** @id MochiKit.DateTime.toPaddedAmericanDate */ | |||
|
150 | MochiKit.DateTime.toPaddedAmericanDate = function (d) { | |||
|
151 | if (typeof(d) == "undefined" || d === null) { | |||
|
152 | return null; | |||
|
153 | } | |||
|
154 | var _padTwo = MochiKit.DateTime._padTwo; | |||
|
155 | return [ | |||
|
156 | _padTwo(d.getMonth() + 1), | |||
|
157 | _padTwo(d.getDate()), | |||
|
158 | d.getFullYear() | |||
|
159 | ].join('/'); | |||
|
160 | }; | |||
|
161 | ||||
|
162 | /** @id MochiKit.DateTime.toAmericanDate */ | |||
|
163 | MochiKit.DateTime.toAmericanDate = function (d) { | |||
|
164 | if (typeof(d) == "undefined" || d === null) { | |||
|
165 | return null; | |||
|
166 | } | |||
|
167 | return [d.getMonth() + 1, d.getDate(), d.getFullYear()].join('/'); | |||
|
168 | }; | |||
|
169 | ||||
|
170 | MochiKit.DateTime.EXPORT = [ | |||
|
171 | "isoDate", | |||
|
172 | "isoTimestamp", | |||
|
173 | "toISOTime", | |||
|
174 | "toISOTimestamp", | |||
|
175 | "toISODate", | |||
|
176 | "americanDate", | |||
|
177 | "toPaddedAmericanDate", | |||
|
178 | "toAmericanDate" | |||
|
179 | ]; | |||
|
180 | ||||
|
181 | MochiKit.DateTime.EXPORT_OK = []; | |||
|
182 | MochiKit.DateTime.EXPORT_TAGS = { | |||
|
183 | ":common": MochiKit.DateTime.EXPORT, | |||
|
184 | ":all": MochiKit.DateTime.EXPORT | |||
|
185 | }; | |||
|
186 | ||||
|
187 | MochiKit.DateTime.__new__ = function () { | |||
|
188 | // MochiKit.Base.nameFunctions(this); | |||
|
189 | var base = this.NAME + "."; | |||
|
190 | for (var k in this) { | |||
|
191 | var o = this[k]; | |||
|
192 | if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') { | |||
|
193 | try { | |||
|
194 | o.NAME = base + k; | |||
|
195 | } catch (e) { | |||
|
196 | // pass | |||
|
197 | } | |||
|
198 | } | |||
|
199 | } | |||
|
200 | }; | |||
|
201 | ||||
|
202 | MochiKit.DateTime.__new__(); | |||
|
203 | ||||
|
204 | if (typeof(MochiKit.Base) != "undefined") { | |||
|
205 | MochiKit.Base._exportSymbols(this, MochiKit.DateTime); | |||
|
206 | } else { | |||
|
207 | (function (globals, module) { | |||
|
208 | if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined') | |||
|
209 | || (MochiKit.__export__ === false)) { | |||
|
210 | var all = module.EXPORT_TAGS[":all"]; | |||
|
211 | for (var i = 0; i < all.length; i++) { | |||
|
212 | globals[all[i]] = module[all[i]]; | |||
|
213 | } | |||
|
214 | } | |||
|
215 | })(this, MochiKit.DateTime); | |||
|
216 | } |
This diff has been collapsed as it changes many lines, (824 lines changed) Show them Hide them | |||||
@@ -0,0 +1,824 b'' | |||||
|
1 | /*** | |||
|
2 | MochiKit.DragAndDrop 1.4 | |||
|
3 | ||||
|
4 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
5 | ||||
|
6 | Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) | |||
|
7 | Mochi-ized By Thomas Herve (_firstname_@nimail.org) | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.DragAndDrop'); | |||
|
13 | dojo.require('MochiKit.Base'); | |||
|
14 | dojo.require('MochiKit.DOM'); | |||
|
15 | dojo.require('MochiKit.Iter'); | |||
|
16 | dojo.require('MochiKit.Visual'); | |||
|
17 | dojo.require('MochiKit.Signal'); | |||
|
18 | } | |||
|
19 | ||||
|
20 | if (typeof(JSAN) != 'undefined') { | |||
|
21 | JSAN.use("MochiKit.Base", []); | |||
|
22 | JSAN.use("MochiKit.DOM", []); | |||
|
23 | JSAN.use("MochiKit.Visual", []); | |||
|
24 | JSAN.use("MochiKit.Iter", []); | |||
|
25 | JSAN.use("MochiKit.Signal", []); | |||
|
26 | } | |||
|
27 | ||||
|
28 | try { | |||
|
29 | if (typeof(MochiKit.Base) == 'undefined' || | |||
|
30 | typeof(MochiKit.DOM) == 'undefined' || | |||
|
31 | typeof(MochiKit.Visual) == 'undefined' || | |||
|
32 | typeof(MochiKit.Signal) == 'undefined' || | |||
|
33 | typeof(MochiKit.Iter) == 'undefined') { | |||
|
34 | throw ""; | |||
|
35 | } | |||
|
36 | } catch (e) { | |||
|
37 | throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM, MochiKit.Visual, MochiKit.Signal and MochiKit.Iter!"; | |||
|
38 | } | |||
|
39 | ||||
|
40 | if (typeof(MochiKit.DragAndDrop) == 'undefined') { | |||
|
41 | MochiKit.DragAndDrop = {}; | |||
|
42 | } | |||
|
43 | ||||
|
44 | MochiKit.DragAndDrop.NAME = 'MochiKit.DragAndDrop'; | |||
|
45 | MochiKit.DragAndDrop.VERSION = '1.4'; | |||
|
46 | ||||
|
47 | MochiKit.DragAndDrop.__repr__ = function () { | |||
|
48 | return '[' + this.NAME + ' ' + this.VERSION + ']'; | |||
|
49 | }; | |||
|
50 | ||||
|
51 | MochiKit.DragAndDrop.toString = function () { | |||
|
52 | return this.__repr__(); | |||
|
53 | }; | |||
|
54 | ||||
|
55 | MochiKit.DragAndDrop.EXPORT = [ | |||
|
56 | "Droppable", | |||
|
57 | "Draggable" | |||
|
58 | ]; | |||
|
59 | ||||
|
60 | MochiKit.DragAndDrop.EXPORT_OK = [ | |||
|
61 | "Droppables", | |||
|
62 | "Draggables" | |||
|
63 | ]; | |||
|
64 | ||||
|
65 | MochiKit.DragAndDrop.Droppables = { | |||
|
66 | /*** | |||
|
67 | ||||
|
68 | Manage all droppables. Shouldn't be used, use the Droppable object instead. | |||
|
69 | ||||
|
70 | ***/ | |||
|
71 | drops: [], | |||
|
72 | ||||
|
73 | remove: function (element) { | |||
|
74 | this.drops = MochiKit.Base.filter(function (d) { | |||
|
75 | return d.element != MochiKit.DOM.getElement(element); | |||
|
76 | }, this.drops); | |||
|
77 | }, | |||
|
78 | ||||
|
79 | register: function (drop) { | |||
|
80 | this.drops.push(drop); | |||
|
81 | }, | |||
|
82 | ||||
|
83 | unregister: function (drop) { | |||
|
84 | this.drops = MochiKit.Base.filter(function (d) { | |||
|
85 | return d != drop; | |||
|
86 | }, this.drops); | |||
|
87 | }, | |||
|
88 | ||||
|
89 | prepare: function (element) { | |||
|
90 | MochiKit.Base.map(function (drop) { | |||
|
91 | if (drop.isAccepted(element)) { | |||
|
92 | if (drop.options.activeclass) { | |||
|
93 | MochiKit.DOM.addElementClass(drop.element, | |||
|
94 | drop.options.activeclass); | |||
|
95 | } | |||
|
96 | drop.options.onactive(drop.element, element); | |||
|
97 | } | |||
|
98 | }, this.drops); | |||
|
99 | }, | |||
|
100 | ||||
|
101 | findDeepestChild: function (drops) { | |||
|
102 | deepest = drops[0]; | |||
|
103 | ||||
|
104 | for (i = 1; i < drops.length; ++i) { | |||
|
105 | if (MochiKit.DOM.isParent(drops[i].element, deepest.element)) { | |||
|
106 | deepest = drops[i]; | |||
|
107 | } | |||
|
108 | } | |||
|
109 | return deepest; | |||
|
110 | }, | |||
|
111 | ||||
|
112 | show: function (point, element) { | |||
|
113 | if (!this.drops.length) { | |||
|
114 | return; | |||
|
115 | } | |||
|
116 | var affected = []; | |||
|
117 | ||||
|
118 | if (this.last_active) { | |||
|
119 | this.last_active.deactivate(); | |||
|
120 | } | |||
|
121 | MochiKit.Iter.forEach(this.drops, function (drop) { | |||
|
122 | if (drop.isAffected(point, element)) { | |||
|
123 | affected.push(drop); | |||
|
124 | } | |||
|
125 | }); | |||
|
126 | if (affected.length > 0) { | |||
|
127 | drop = this.findDeepestChild(affected); | |||
|
128 | MochiKit.Position.within(drop.element, point.page.x, point.page.y); | |||
|
129 | drop.options.onhover(element, drop.element, | |||
|
130 | MochiKit.Position.overlap(drop.options.overlap, drop.element)); | |||
|
131 | drop.activate(); | |||
|
132 | } | |||
|
133 | }, | |||
|
134 | ||||
|
135 | fire: function (event, element) { | |||
|
136 | if (!this.last_active) { | |||
|
137 | return; | |||
|
138 | } | |||
|
139 | MochiKit.Position.prepare(); | |||
|
140 | ||||
|
141 | if (this.last_active.isAffected(event.mouse(), element)) { | |||
|
142 | this.last_active.options.ondrop(element, | |||
|
143 | this.last_active.element, event); | |||
|
144 | } | |||
|
145 | }, | |||
|
146 | ||||
|
147 | reset: function (element) { | |||
|
148 | MochiKit.Base.map(function (drop) { | |||
|
149 | if (drop.options.activeclass) { | |||
|
150 | MochiKit.DOM.removeElementClass(drop.element, | |||
|
151 | drop.options.activeclass); | |||
|
152 | } | |||
|
153 | drop.options.ondesactive(drop.element, element); | |||
|
154 | }, this.drops); | |||
|
155 | if (this.last_active) { | |||
|
156 | this.last_active.deactivate(); | |||
|
157 | } | |||
|
158 | } | |||
|
159 | }; | |||
|
160 | ||||
|
161 | /** @id MochiKit.DragAndDrop.Droppable */ | |||
|
162 | MochiKit.DragAndDrop.Droppable = function (element, options) { | |||
|
163 | var cls = arguments.callee; | |||
|
164 | if (!(this instanceof cls)) { | |||
|
165 | return new cls(element, options); | |||
|
166 | } | |||
|
167 | this.__init__(element, options); | |||
|
168 | }; | |||
|
169 | ||||
|
170 | MochiKit.DragAndDrop.Droppable.prototype = { | |||
|
171 | /*** | |||
|
172 | ||||
|
173 | A droppable object. Simple use is to create giving an element: | |||
|
174 | ||||
|
175 | new MochiKit.DragAndDrop.Droppable('myelement'); | |||
|
176 | ||||
|
177 | Generally you'll want to define the 'ondrop' function and maybe the | |||
|
178 | 'accept' option to filter draggables. | |||
|
179 | ||||
|
180 | ***/ | |||
|
181 | __class__: MochiKit.DragAndDrop.Droppable, | |||
|
182 | ||||
|
183 | __init__: function (element, /* optional */options) { | |||
|
184 | var d = MochiKit.DOM; | |||
|
185 | var b = MochiKit.Base; | |||
|
186 | this.element = d.getElement(element); | |||
|
187 | this.options = b.update({ | |||
|
188 | ||||
|
189 | /** @id MochiKit.DragAndDrop.greedy */ | |||
|
190 | greedy: true, | |||
|
191 | ||||
|
192 | /** @id MochiKit.DragAndDrop.hoverclass */ | |||
|
193 | hoverclass: null, | |||
|
194 | ||||
|
195 | /** @id MochiKit.DragAndDrop.activeclass */ | |||
|
196 | activeclass: null, | |||
|
197 | ||||
|
198 | /** @id MochiKit.DragAndDrop.hoverfunc */ | |||
|
199 | hoverfunc: b.noop, | |||
|
200 | ||||
|
201 | /** @id MochiKit.DragAndDrop.accept */ | |||
|
202 | accept: null, | |||
|
203 | ||||
|
204 | /** @id MochiKit.DragAndDrop.onactive */ | |||
|
205 | onactive: b.noop, | |||
|
206 | ||||
|
207 | /** @id MochiKit.DragAndDrop.ondesactive */ | |||
|
208 | ondesactive: b.noop, | |||
|
209 | ||||
|
210 | /** @id MochiKit.DragAndDrop.onhover */ | |||
|
211 | onhover: b.noop, | |||
|
212 | ||||
|
213 | /** @id MochiKit.DragAndDrop.ondrop */ | |||
|
214 | ondrop: b.noop, | |||
|
215 | ||||
|
216 | /** @id MochiKit.DragAndDrop.containment */ | |||
|
217 | containment: [], | |||
|
218 | tree: false | |||
|
219 | }, options); | |||
|
220 | ||||
|
221 | // cache containers | |||
|
222 | this.options._containers = []; | |||
|
223 | b.map(MochiKit.Base.bind(function (c) { | |||
|
224 | this.options._containers.push(d.getElement(c)); | |||
|
225 | }, this), this.options.containment); | |||
|
226 | ||||
|
227 | d.makePositioned(this.element); // fix IE | |||
|
228 | ||||
|
229 | MochiKit.DragAndDrop.Droppables.register(this); | |||
|
230 | }, | |||
|
231 | ||||
|
232 | /** @id MochiKit.DragAndDrop.isContained */ | |||
|
233 | isContained: function (element) { | |||
|
234 | if (this.options._containers.length) { | |||
|
235 | var containmentNode; | |||
|
236 | if (this.options.tree) { | |||
|
237 | containmentNode = element.treeNode; | |||
|
238 | } else { | |||
|
239 | containmentNode = element.parentNode; | |||
|
240 | } | |||
|
241 | return MochiKit.Iter.some(this.options._containers, function (c) { | |||
|
242 | return containmentNode == c; | |||
|
243 | }); | |||
|
244 | } else { | |||
|
245 | return true; | |||
|
246 | } | |||
|
247 | }, | |||
|
248 | ||||
|
249 | /** @id MochiKit.DragAndDrop.isAccepted */ | |||
|
250 | isAccepted: function (element) { | |||
|
251 | return ((!this.options.accept) || MochiKit.Iter.some( | |||
|
252 | this.options.accept, function (c) { | |||
|
253 | return MochiKit.DOM.hasElementClass(element, c); | |||
|
254 | })); | |||
|
255 | }, | |||
|
256 | ||||
|
257 | /** @id MochiKit.DragAndDrop.isAffected */ | |||
|
258 | isAffected: function (point, element) { | |||
|
259 | return ((this.element != element) && | |||
|
260 | this.isContained(element) && | |||
|
261 | this.isAccepted(element) && | |||
|
262 | MochiKit.Position.within(this.element, point.page.x, | |||
|
263 | point.page.y)); | |||
|
264 | }, | |||
|
265 | ||||
|
266 | /** @id MochiKit.DragAndDrop.deactivate */ | |||
|
267 | deactivate: function () { | |||
|
268 | /*** | |||
|
269 | ||||
|
270 | A droppable is deactivate when a draggable has been over it and left. | |||
|
271 | ||||
|
272 | ***/ | |||
|
273 | if (this.options.hoverclass) { | |||
|
274 | MochiKit.DOM.removeElementClass(this.element, | |||
|
275 | this.options.hoverclass); | |||
|
276 | } | |||
|
277 | this.options.hoverfunc(this.element, false); | |||
|
278 | MochiKit.DragAndDrop.Droppables.last_active = null; | |||
|
279 | }, | |||
|
280 | ||||
|
281 | /** @id MochiKit.DragAndDrop.activate */ | |||
|
282 | activate: function () { | |||
|
283 | /*** | |||
|
284 | ||||
|
285 | A droppable is active when a draggable is over it. | |||
|
286 | ||||
|
287 | ***/ | |||
|
288 | if (this.options.hoverclass) { | |||
|
289 | MochiKit.DOM.addElementClass(this.element, this.options.hoverclass); | |||
|
290 | } | |||
|
291 | this.options.hoverfunc(this.element, true); | |||
|
292 | MochiKit.DragAndDrop.Droppables.last_active = this; | |||
|
293 | }, | |||
|
294 | ||||
|
295 | /** @id MochiKit.DragAndDrop.destroy */ | |||
|
296 | destroy: function () { | |||
|
297 | /*** | |||
|
298 | ||||
|
299 | Delete this droppable. | |||
|
300 | ||||
|
301 | ***/ | |||
|
302 | MochiKit.DragAndDrop.Droppables.unregister(this); | |||
|
303 | }, | |||
|
304 | ||||
|
305 | /** @id MochiKit.DragAndDrop.repr */ | |||
|
306 | repr: function () { | |||
|
307 | return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]"; | |||
|
308 | } | |||
|
309 | }; | |||
|
310 | ||||
|
311 | MochiKit.DragAndDrop.Draggables = { | |||
|
312 | /*** | |||
|
313 | ||||
|
314 | Manage draggables elements. Not intended to direct use. | |||
|
315 | ||||
|
316 | ***/ | |||
|
317 | drags: [], | |||
|
318 | ||||
|
319 | register: function (draggable) { | |||
|
320 | if (this.drags.length === 0) { | |||
|
321 | var conn = MochiKit.Signal.connect; | |||
|
322 | this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag); | |||
|
323 | this.eventMouseMove = conn(document, 'onmousemove', this, | |||
|
324 | this.updateDrag); | |||
|
325 | this.eventKeypress = conn(document, 'onkeypress', this, | |||
|
326 | this.keyPress); | |||
|
327 | } | |||
|
328 | this.drags.push(draggable); | |||
|
329 | }, | |||
|
330 | ||||
|
331 | unregister: function (draggable) { | |||
|
332 | this.drags = MochiKit.Base.filter(function (d) { | |||
|
333 | return d != draggable; | |||
|
334 | }, this.drags); | |||
|
335 | if (this.drags.length === 0) { | |||
|
336 | var disc = MochiKit.Signal.disconnect; | |||
|
337 | disc(this.eventMouseUp); | |||
|
338 | disc(this.eventMouseMove); | |||
|
339 | disc(this.eventKeypress); | |||
|
340 | } | |||
|
341 | }, | |||
|
342 | ||||
|
343 | activate: function (draggable) { | |||
|
344 | // allows keypress events if window is not currently focused | |||
|
345 | // fails for Safari | |||
|
346 | window.focus(); | |||
|
347 | this.activeDraggable = draggable; | |||
|
348 | }, | |||
|
349 | ||||
|
350 | deactivate: function () { | |||
|
351 | this.activeDraggable = null; | |||
|
352 | }, | |||
|
353 | ||||
|
354 | updateDrag: function (event) { | |||
|
355 | if (!this.activeDraggable) { | |||
|
356 | return; | |||
|
357 | } | |||
|
358 | var pointer = event.mouse(); | |||
|
359 | // Mozilla-based browsers fire successive mousemove events with | |||
|
360 | // the same coordinates, prevent needless redrawing (moz bug?) | |||
|
361 | if (this._lastPointer && (MochiKit.Base.repr(this._lastPointer.page) == | |||
|
362 | MochiKit.Base.repr(pointer.page))) { | |||
|
363 | return; | |||
|
364 | } | |||
|
365 | this._lastPointer = pointer; | |||
|
366 | this.activeDraggable.updateDrag(event, pointer); | |||
|
367 | }, | |||
|
368 | ||||
|
369 | endDrag: function (event) { | |||
|
370 | if (!this.activeDraggable) { | |||
|
371 | return; | |||
|
372 | } | |||
|
373 | this._lastPointer = null; | |||
|
374 | this.activeDraggable.endDrag(event); | |||
|
375 | this.activeDraggable = null; | |||
|
376 | }, | |||
|
377 | ||||
|
378 | keyPress: function (event) { | |||
|
379 | if (this.activeDraggable) { | |||
|
380 | this.activeDraggable.keyPress(event); | |||
|
381 | } | |||
|
382 | }, | |||
|
383 | ||||
|
384 | notify: function (eventName, draggable, event) { | |||
|
385 | MochiKit.Signal.signal(this, eventName, draggable, event); | |||
|
386 | } | |||
|
387 | }; | |||
|
388 | ||||
|
389 | /** @id MochiKit.DragAndDrop.Draggable */ | |||
|
390 | MochiKit.DragAndDrop.Draggable = function (element, options) { | |||
|
391 | var cls = arguments.callee; | |||
|
392 | if (!(this instanceof cls)) { | |||
|
393 | return new cls(element, options); | |||
|
394 | } | |||
|
395 | this.__init__(element, options); | |||
|
396 | }; | |||
|
397 | ||||
|
398 | MochiKit.DragAndDrop.Draggable.prototype = { | |||
|
399 | /*** | |||
|
400 | ||||
|
401 | A draggable object. Simple instantiate : | |||
|
402 | ||||
|
403 | new MochiKit.DragAndDrop.Draggable('myelement'); | |||
|
404 | ||||
|
405 | ***/ | |||
|
406 | __class__ : MochiKit.DragAndDrop.Draggable, | |||
|
407 | ||||
|
408 | __init__: function (element, /* optional */options) { | |||
|
409 | var v = MochiKit.Visual; | |||
|
410 | var b = MochiKit.Base; | |||
|
411 | options = b.update({ | |||
|
412 | ||||
|
413 | /** @id MochiKit.DragAndDrop.handle */ | |||
|
414 | handle: false, | |||
|
415 | ||||
|
416 | /** @id MochiKit.DragAndDrop.starteffect */ | |||
|
417 | starteffect: function (innerelement) { | |||
|
418 | this._savedOpacity = MochiKit.Style.getStyle(innerelement, 'opacity') || 1.0; | |||
|
419 | new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7}); | |||
|
420 | }, | |||
|
421 | /** @id MochiKit.DragAndDrop.reverteffect */ | |||
|
422 | reverteffect: function (innerelement, top_offset, left_offset) { | |||
|
423 | var dur = Math.sqrt(Math.abs(top_offset^2) + | |||
|
424 | Math.abs(left_offset^2))*0.02; | |||
|
425 | return new v.Move(innerelement, | |||
|
426 | {x: -left_offset, y: -top_offset, duration: dur}); | |||
|
427 | }, | |||
|
428 | ||||
|
429 | /** @id MochiKit.DragAndDrop.endeffect */ | |||
|
430 | endeffect: function (innerelement) { | |||
|
431 | new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity}); | |||
|
432 | }, | |||
|
433 | ||||
|
434 | /** @id MochiKit.DragAndDrop.onchange */ | |||
|
435 | onchange: b.noop, | |||
|
436 | ||||
|
437 | /** @id MochiKit.DragAndDrop.zindex */ | |||
|
438 | zindex: 1000, | |||
|
439 | ||||
|
440 | /** @id MochiKit.DragAndDrop.revert */ | |||
|
441 | revert: false, | |||
|
442 | ||||
|
443 | /** @id MochiKit.DragAndDrop.scroll */ | |||
|
444 | scroll: false, | |||
|
445 | ||||
|
446 | /** @id MochiKit.DragAndDrop.scrollSensitivity */ | |||
|
447 | scrollSensitivity: 20, | |||
|
448 | ||||
|
449 | /** @id MochiKit.DragAndDrop.scrollSpeed */ | |||
|
450 | scrollSpeed: 15, | |||
|
451 | // false, or xy or [x, y] or function (x, y){return [x, y];} | |||
|
452 | ||||
|
453 | /** @id MochiKit.DragAndDrop.snap */ | |||
|
454 | snap: false | |||
|
455 | }, options); | |||
|
456 | ||||
|
457 | var d = MochiKit.DOM; | |||
|
458 | this.element = d.getElement(element); | |||
|
459 | ||||
|
460 | if (options.handle && (typeof(options.handle) == 'string')) { | |||
|
461 | this.handle = d.getFirstElementByTagAndClassName(null, | |||
|
462 | options.handle, this.element); | |||
|
463 | } | |||
|
464 | if (!this.handle) { | |||
|
465 | this.handle = d.getElement(options.handle); | |||
|
466 | } | |||
|
467 | if (!this.handle) { | |||
|
468 | this.handle = this.element; | |||
|
469 | } | |||
|
470 | ||||
|
471 | if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { | |||
|
472 | options.scroll = d.getElement(options.scroll); | |||
|
473 | this._isScrollChild = MochiKit.DOM.isChildNode(this.element, options.scroll); | |||
|
474 | } | |||
|
475 | ||||
|
476 | d.makePositioned(this.element); // fix IE | |||
|
477 | ||||
|
478 | this.delta = this.currentDelta(); | |||
|
479 | this.options = options; | |||
|
480 | this.dragging = false; | |||
|
481 | ||||
|
482 | this.eventMouseDown = MochiKit.Signal.connect(this.handle, | |||
|
483 | 'onmousedown', this, this.initDrag); | |||
|
484 | MochiKit.DragAndDrop.Draggables.register(this); | |||
|
485 | }, | |||
|
486 | ||||
|
487 | /** @id MochiKit.DragAndDrop.destroy */ | |||
|
488 | destroy: function () { | |||
|
489 | MochiKit.Signal.disconnect(this.eventMouseDown); | |||
|
490 | MochiKit.DragAndDrop.Draggables.unregister(this); | |||
|
491 | }, | |||
|
492 | ||||
|
493 | /** @id MochiKit.DragAndDrop.currentDelta */ | |||
|
494 | currentDelta: function () { | |||
|
495 | var s = MochiKit.Style.getStyle; | |||
|
496 | return [ | |||
|
497 | parseInt(s(this.element, 'left') || '0'), | |||
|
498 | parseInt(s(this.element, 'top') || '0')]; | |||
|
499 | }, | |||
|
500 | ||||
|
501 | /** @id MochiKit.DragAndDrop.initDrag */ | |||
|
502 | initDrag: function (event) { | |||
|
503 | if (!event.mouse().button.left) { | |||
|
504 | return; | |||
|
505 | } | |||
|
506 | // abort on form elements, fixes a Firefox issue | |||
|
507 | var src = event.target(); | |||
|
508 | var tagName = (src.tagName || '').toUpperCase(); | |||
|
509 | if (tagName === 'INPUT' || tagName === 'SELECT' || | |||
|
510 | tagName === 'OPTION' || tagName === 'BUTTON' || | |||
|
511 | tagName === 'TEXTAREA') { | |||
|
512 | return; | |||
|
513 | } | |||
|
514 | ||||
|
515 | if (this._revert) { | |||
|
516 | this._revert.cancel(); | |||
|
517 | this._revert = null; | |||
|
518 | } | |||
|
519 | ||||
|
520 | var pointer = event.mouse(); | |||
|
521 | var pos = MochiKit.Position.cumulativeOffset(this.element); | |||
|
522 | this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y]; | |||
|
523 | ||||
|
524 | MochiKit.DragAndDrop.Draggables.activate(this); | |||
|
525 | event.stop(); | |||
|
526 | }, | |||
|
527 | ||||
|
528 | /** @id MochiKit.DragAndDrop.startDrag */ | |||
|
529 | startDrag: function (event) { | |||
|
530 | this.dragging = true; | |||
|
531 | if (this.options.selectclass) { | |||
|
532 | MochiKit.DOM.addElementClass(this.element, | |||
|
533 | this.options.selectclass); | |||
|
534 | } | |||
|
535 | if (this.options.zindex) { | |||
|
536 | this.originalZ = parseInt(MochiKit.Style.getStyle(this.element, | |||
|
537 | 'z-index') || '0'); | |||
|
538 | this.element.style.zIndex = this.options.zindex; | |||
|
539 | } | |||
|
540 | ||||
|
541 | if (this.options.ghosting) { | |||
|
542 | this._clone = this.element.cloneNode(true); | |||
|
543 | this.ghostPosition = MochiKit.Position.absolutize(this.element); | |||
|
544 | this.element.parentNode.insertBefore(this._clone, this.element); | |||
|
545 | } | |||
|
546 | ||||
|
547 | if (this.options.scroll) { | |||
|
548 | if (this.options.scroll == window) { | |||
|
549 | var where = this._getWindowScroll(this.options.scroll); | |||
|
550 | this.originalScrollLeft = where.left; | |||
|
551 | this.originalScrollTop = where.top; | |||
|
552 | } else { | |||
|
553 | this.originalScrollLeft = this.options.scroll.scrollLeft; | |||
|
554 | this.originalScrollTop = this.options.scroll.scrollTop; | |||
|
555 | } | |||
|
556 | } | |||
|
557 | ||||
|
558 | MochiKit.DragAndDrop.Droppables.prepare(this.element); | |||
|
559 | MochiKit.DragAndDrop.Draggables.notify('start', this, event); | |||
|
560 | if (this.options.starteffect) { | |||
|
561 | this.options.starteffect(this.element); | |||
|
562 | } | |||
|
563 | }, | |||
|
564 | ||||
|
565 | /** @id MochiKit.DragAndDrop.updateDrag */ | |||
|
566 | updateDrag: function (event, pointer) { | |||
|
567 | if (!this.dragging) { | |||
|
568 | this.startDrag(event); | |||
|
569 | } | |||
|
570 | MochiKit.Position.prepare(); | |||
|
571 | MochiKit.DragAndDrop.Droppables.show(pointer, this.element); | |||
|
572 | MochiKit.DragAndDrop.Draggables.notify('drag', this, event); | |||
|
573 | this.draw(pointer); | |||
|
574 | this.options.onchange(this); | |||
|
575 | ||||
|
576 | if (this.options.scroll) { | |||
|
577 | this.stopScrolling(); | |||
|
578 | var p, q; | |||
|
579 | if (this.options.scroll == window) { | |||
|
580 | var s = this._getWindowScroll(this.options.scroll); | |||
|
581 | p = new MochiKit.Style.Coordinates(s.left, s.top); | |||
|
582 | q = new MochiKit.Style.Coordinates(s.left + s.width, | |||
|
583 | s.top + s.height); | |||
|
584 | } else { | |||
|
585 | p = MochiKit.Position.page(this.options.scroll); | |||
|
586 | p.x += this.options.scroll.scrollLeft; | |||
|
587 | p.y += this.options.scroll.scrollTop; | |||
|
588 | p.x += (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0); | |||
|
589 | p.y += (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0); | |||
|
590 | q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth, | |||
|
591 | p.y + this.options.scroll.offsetHeight); | |||
|
592 | } | |||
|
593 | var speed = [0, 0]; | |||
|
594 | if (pointer.page.x > (q.x - this.options.scrollSensitivity)) { | |||
|
595 | speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity); | |||
|
596 | } else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) { | |||
|
597 | speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity); | |||
|
598 | } | |||
|
599 | if (pointer.page.y > (q.y - this.options.scrollSensitivity)) { | |||
|
600 | speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity); | |||
|
601 | } else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) { | |||
|
602 | speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity); | |||
|
603 | } | |||
|
604 | this.startScrolling(speed); | |||
|
605 | } | |||
|
606 | ||||
|
607 | // fix AppleWebKit rendering | |||
|
608 | if (/AppleWebKit'/.test(navigator.appVersion)) { | |||
|
609 | window.scrollBy(0, 0); | |||
|
610 | } | |||
|
611 | event.stop(); | |||
|
612 | }, | |||
|
613 | ||||
|
614 | /** @id MochiKit.DragAndDrop.finishDrag */ | |||
|
615 | finishDrag: function (event, success) { | |||
|
616 | var dr = MochiKit.DragAndDrop; | |||
|
617 | this.dragging = false; | |||
|
618 | if (this.options.selectclass) { | |||
|
619 | MochiKit.DOM.removeElementClass(this.element, | |||
|
620 | this.options.selectclass); | |||
|
621 | } | |||
|
622 | ||||
|
623 | if (this.options.ghosting) { | |||
|
624 | // XXX: from a user point of view, it would be better to remove | |||
|
625 | // the node only *after* the MochiKit.Visual.Move end when used | |||
|
626 | // with revert. | |||
|
627 | MochiKit.Position.relativize(this.element, this.ghostPosition); | |||
|
628 | MochiKit.DOM.removeElement(this._clone); | |||
|
629 | this._clone = null; | |||
|
630 | } | |||
|
631 | ||||
|
632 | if (success) { | |||
|
633 | dr.Droppables.fire(event, this.element); | |||
|
634 | } | |||
|
635 | dr.Draggables.notify('end', this, event); | |||
|
636 | ||||
|
637 | var revert = this.options.revert; | |||
|
638 | if (revert && typeof(revert) == 'function') { | |||
|
639 | revert = revert(this.element); | |||
|
640 | } | |||
|
641 | ||||
|
642 | var d = this.currentDelta(); | |||
|
643 | if (revert && this.options.reverteffect) { | |||
|
644 | this._revert = this.options.reverteffect(this.element, | |||
|
645 | d[1] - this.delta[1], d[0] - this.delta[0]); | |||
|
646 | } else { | |||
|
647 | this.delta = d; | |||
|
648 | } | |||
|
649 | ||||
|
650 | if (this.options.zindex) { | |||
|
651 | this.element.style.zIndex = this.originalZ; | |||
|
652 | } | |||
|
653 | ||||
|
654 | if (this.options.endeffect) { | |||
|
655 | this.options.endeffect(this.element); | |||
|
656 | } | |||
|
657 | ||||
|
658 | dr.Draggables.deactivate(); | |||
|
659 | dr.Droppables.reset(this.element); | |||
|
660 | }, | |||
|
661 | ||||
|
662 | /** @id MochiKit.DragAndDrop.keyPress */ | |||
|
663 | keyPress: function (event) { | |||
|
664 | if (event.key().string != "KEY_ESCAPE") { | |||
|
665 | return; | |||
|
666 | } | |||
|
667 | this.finishDrag(event, false); | |||
|
668 | event.stop(); | |||
|
669 | }, | |||
|
670 | ||||
|
671 | /** @id MochiKit.DragAndDrop.endDrag */ | |||
|
672 | endDrag: function (event) { | |||
|
673 | if (!this.dragging) { | |||
|
674 | return; | |||
|
675 | } | |||
|
676 | this.stopScrolling(); | |||
|
677 | this.finishDrag(event, true); | |||
|
678 | event.stop(); | |||
|
679 | }, | |||
|
680 | ||||
|
681 | /** @id MochiKit.DragAndDrop.draw */ | |||
|
682 | draw: function (point) { | |||
|
683 | var pos = MochiKit.Position.cumulativeOffset(this.element); | |||
|
684 | var d = this.currentDelta(); | |||
|
685 | pos.x -= d[0]; | |||
|
686 | pos.y -= d[1]; | |||
|
687 | ||||
|
688 | if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { | |||
|
689 | pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft; | |||
|
690 | pos.y -= this.options.scroll.scrollTop - this.originalScrollTop; | |||
|
691 | } | |||
|
692 | ||||
|
693 | var p = [point.page.x - pos.x - this.offset[0], | |||
|
694 | point.page.y - pos.y - this.offset[1]]; | |||
|
695 | ||||
|
696 | if (this.options.snap) { | |||
|
697 | if (typeof(this.options.snap) == 'function') { | |||
|
698 | p = this.options.snap(p[0], p[1]); | |||
|
699 | } else { | |||
|
700 | if (this.options.snap instanceof Array) { | |||
|
701 | var i = -1; | |||
|
702 | p = MochiKit.Base.map(MochiKit.Base.bind(function (v) { | |||
|
703 | i += 1; | |||
|
704 | return Math.round(v/this.options.snap[i]) * | |||
|
705 | this.options.snap[i]; | |||
|
706 | }, this), p); | |||
|
707 | } else { | |||
|
708 | p = MochiKit.Base.map(MochiKit.Base.bind(function (v) { | |||
|
709 | return Math.round(v/this.options.snap) * | |||
|
710 | this.options.snap; | |||
|
711 | }, this), p); | |||
|
712 | } | |||
|
713 | } | |||
|
714 | } | |||
|
715 | var style = this.element.style; | |||
|
716 | if ((!this.options.constraint) || | |||
|
717 | (this.options.constraint == 'horizontal')) { | |||
|
718 | style.left = p[0] + 'px'; | |||
|
719 | } | |||
|
720 | if ((!this.options.constraint) || | |||
|
721 | (this.options.constraint == 'vertical')) { | |||
|
722 | style.top = p[1] + 'px'; | |||
|
723 | } | |||
|
724 | if (style.visibility == 'hidden') { | |||
|
725 | style.visibility = ''; // fix gecko rendering | |||
|
726 | } | |||
|
727 | }, | |||
|
728 | ||||
|
729 | /** @id MochiKit.DragAndDrop.stopScrolling */ | |||
|
730 | stopScrolling: function () { | |||
|
731 | if (this.scrollInterval) { | |||
|
732 | clearInterval(this.scrollInterval); | |||
|
733 | this.scrollInterval = null; | |||
|
734 | MochiKit.DragAndDrop.Draggables._lastScrollPointer = null; | |||
|
735 | } | |||
|
736 | }, | |||
|
737 | ||||
|
738 | /** @id MochiKit.DragAndDrop.startScrolling */ | |||
|
739 | startScrolling: function (speed) { | |||
|
740 | if (!speed[0] && !speed[1]) { | |||
|
741 | return; | |||
|
742 | } | |||
|
743 | this.scrollSpeed = [speed[0] * this.options.scrollSpeed, | |||
|
744 | speed[1] * this.options.scrollSpeed]; | |||
|
745 | this.lastScrolled = new Date(); | |||
|
746 | this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10); | |||
|
747 | }, | |||
|
748 | ||||
|
749 | /** @id MochiKit.DragAndDrop.scroll */ | |||
|
750 | scroll: function () { | |||
|
751 | var current = new Date(); | |||
|
752 | var delta = current - this.lastScrolled; | |||
|
753 | this.lastScrolled = current; | |||
|
754 | ||||
|
755 | if (this.options.scroll == window) { | |||
|
756 | var s = this._getWindowScroll(this.options.scroll); | |||
|
757 | if (this.scrollSpeed[0] || this.scrollSpeed[1]) { | |||
|
758 | var dm = delta / 1000; | |||
|
759 | this.options.scroll.scrollTo(s.left + dm * this.scrollSpeed[0], | |||
|
760 | s.top + dm * this.scrollSpeed[1]); | |||
|
761 | } | |||
|
762 | } else { | |||
|
763 | this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; | |||
|
764 | this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; | |||
|
765 | } | |||
|
766 | ||||
|
767 | var d = MochiKit.DragAndDrop; | |||
|
768 | ||||
|
769 | MochiKit.Position.prepare(); | |||
|
770 | d.Droppables.show(d.Draggables._lastPointer, this.element); | |||
|
771 | d.Draggables.notify('drag', this); | |||
|
772 | if (this._isScrollChild) { | |||
|
773 | d.Draggables._lastScrollPointer = d.Draggables._lastScrollPointer || d.Draggables._lastPointer; | |||
|
774 | d.Draggables._lastScrollPointer.x += this.scrollSpeed[0] * delta / 1000; | |||
|
775 | d.Draggables._lastScrollPointer.y += this.scrollSpeed[1] * delta / 1000; | |||
|
776 | if (d.Draggables._lastScrollPointer.x < 0) { | |||
|
777 | d.Draggables._lastScrollPointer.x = 0; | |||
|
778 | } | |||
|
779 | if (d.Draggables._lastScrollPointer.y < 0) { | |||
|
780 | d.Draggables._lastScrollPointer.y = 0; | |||
|
781 | } | |||
|
782 | this.draw(d.Draggables._lastScrollPointer); | |||
|
783 | } | |||
|
784 | ||||
|
785 | this.options.onchange(this); | |||
|
786 | }, | |||
|
787 | ||||
|
788 | _getWindowScroll: function (win) { | |||
|
789 | var vp, w, h; | |||
|
790 | MochiKit.DOM.withWindow(win, function () { | |||
|
791 | vp = MochiKit.Style.getViewportPosition(win.document); | |||
|
792 | }); | |||
|
793 | if (win.innerWidth) { | |||
|
794 | w = win.innerWidth; | |||
|
795 | h = win.innerHeight; | |||
|
796 | } else if (win.document.documentElement && win.document.documentElement.clientWidth) { | |||
|
797 | w = win.document.documentElement.clientWidth; | |||
|
798 | h = win.document.documentElement.clientHeight; | |||
|
799 | } else { | |||
|
800 | w = win.document.body.offsetWidth; | |||
|
801 | h = win.document.body.offsetHeight; | |||
|
802 | } | |||
|
803 | return {top: vp.x, left: vp.y, width: w, height: h}; | |||
|
804 | }, | |||
|
805 | ||||
|
806 | /** @id MochiKit.DragAndDrop.repr */ | |||
|
807 | repr: function () { | |||
|
808 | return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]"; | |||
|
809 | } | |||
|
810 | }; | |||
|
811 | ||||
|
812 | MochiKit.DragAndDrop.__new__ = function () { | |||
|
813 | MochiKit.Base.nameFunctions(this); | |||
|
814 | ||||
|
815 | this.EXPORT_TAGS = { | |||
|
816 | ":common": this.EXPORT, | |||
|
817 | ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK) | |||
|
818 | }; | |||
|
819 | }; | |||
|
820 | ||||
|
821 | MochiKit.DragAndDrop.__new__(); | |||
|
822 | ||||
|
823 | MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop); | |||
|
824 |
@@ -0,0 +1,305 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.Format 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.Format'); | |||
|
13 | } | |||
|
14 | ||||
|
15 | if (typeof(MochiKit) == 'undefined') { | |||
|
16 | MochiKit = {}; | |||
|
17 | } | |||
|
18 | ||||
|
19 | if (typeof(MochiKit.Format) == 'undefined') { | |||
|
20 | MochiKit.Format = {}; | |||
|
21 | } | |||
|
22 | ||||
|
23 | MochiKit.Format.NAME = "MochiKit.Format"; | |||
|
24 | MochiKit.Format.VERSION = "1.4"; | |||
|
25 | MochiKit.Format.__repr__ = function () { | |||
|
26 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
27 | }; | |||
|
28 | MochiKit.Format.toString = function () { | |||
|
29 | return this.__repr__(); | |||
|
30 | }; | |||
|
31 | ||||
|
32 | MochiKit.Format._numberFormatter = function (placeholder, header, footer, locale, isPercent, precision, leadingZeros, separatorAt, trailingZeros) { | |||
|
33 | return function (num) { | |||
|
34 | num = parseFloat(num); | |||
|
35 | if (typeof(num) == "undefined" || num === null || isNaN(num)) { | |||
|
36 | return placeholder; | |||
|
37 | } | |||
|
38 | var curheader = header; | |||
|
39 | var curfooter = footer; | |||
|
40 | if (num < 0) { | |||
|
41 | num = -num; | |||
|
42 | } else { | |||
|
43 | curheader = curheader.replace(/-/, ""); | |||
|
44 | } | |||
|
45 | var me = arguments.callee; | |||
|
46 | var fmt = MochiKit.Format.formatLocale(locale); | |||
|
47 | if (isPercent) { | |||
|
48 | num = num * 100.0; | |||
|
49 | curfooter = fmt.percent + curfooter; | |||
|
50 | } | |||
|
51 | num = MochiKit.Format.roundToFixed(num, precision); | |||
|
52 | var parts = num.split(/\./); | |||
|
53 | var whole = parts[0]; | |||
|
54 | var frac = (parts.length == 1) ? "" : parts[1]; | |||
|
55 | var res = ""; | |||
|
56 | while (whole.length < leadingZeros) { | |||
|
57 | whole = "0" + whole; | |||
|
58 | } | |||
|
59 | if (separatorAt) { | |||
|
60 | while (whole.length > separatorAt) { | |||
|
61 | var i = whole.length - separatorAt; | |||
|
62 | //res = res + fmt.separator + whole.substring(i, whole.length); | |||
|
63 | res = fmt.separator + whole.substring(i, whole.length) + res; | |||
|
64 | whole = whole.substring(0, i); | |||
|
65 | } | |||
|
66 | } | |||
|
67 | res = whole + res; | |||
|
68 | if (precision > 0) { | |||
|
69 | while (frac.length < trailingZeros) { | |||
|
70 | frac = frac + "0"; | |||
|
71 | } | |||
|
72 | res = res + fmt.decimal + frac; | |||
|
73 | } | |||
|
74 | return curheader + res + curfooter; | |||
|
75 | }; | |||
|
76 | }; | |||
|
77 | ||||
|
78 | /** @id MochiKit.Format.numberFormatter */ | |||
|
79 | MochiKit.Format.numberFormatter = function (pattern, placeholder/* = "" */, locale/* = "default" */) { | |||
|
80 | // http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html | |||
|
81 | // | 0 | leading or trailing zeros | |||
|
82 | // | # | just the number | |||
|
83 | // | , | separator | |||
|
84 | // | . | decimal separator | |||
|
85 | // | % | Multiply by 100 and format as percent | |||
|
86 | if (typeof(placeholder) == "undefined") { | |||
|
87 | placeholder = ""; | |||
|
88 | } | |||
|
89 | var match = pattern.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/); | |||
|
90 | if (!match) { | |||
|
91 | throw TypeError("Invalid pattern"); | |||
|
92 | } | |||
|
93 | var header = pattern.substr(0, match.index); | |||
|
94 | var footer = pattern.substr(match.index + match[0].length); | |||
|
95 | if (header.search(/-/) == -1) { | |||
|
96 | header = header + "-"; | |||
|
97 | } | |||
|
98 | var whole = match[1]; | |||
|
99 | var frac = (typeof(match[2]) == "string" && match[2] != "") ? match[2] : ""; | |||
|
100 | var isPercent = (typeof(match[3]) == "string" && match[3] != ""); | |||
|
101 | var tmp = whole.split(/,/); | |||
|
102 | var separatorAt; | |||
|
103 | if (typeof(locale) == "undefined") { | |||
|
104 | locale = "default"; | |||
|
105 | } | |||
|
106 | if (tmp.length == 1) { | |||
|
107 | separatorAt = null; | |||
|
108 | } else { | |||
|
109 | separatorAt = tmp[1].length; | |||
|
110 | } | |||
|
111 | var leadingZeros = whole.length - whole.replace(/0/g, "").length; | |||
|
112 | var trailingZeros = frac.length - frac.replace(/0/g, "").length; | |||
|
113 | var precision = frac.length; | |||
|
114 | var rval = MochiKit.Format._numberFormatter( | |||
|
115 | placeholder, header, footer, locale, isPercent, precision, | |||
|
116 | leadingZeros, separatorAt, trailingZeros | |||
|
117 | ); | |||
|
118 | var m = MochiKit.Base; | |||
|
119 | if (m) { | |||
|
120 | var fn = arguments.callee; | |||
|
121 | var args = m.concat(arguments); | |||
|
122 | rval.repr = function () { | |||
|
123 | return [ | |||
|
124 | self.NAME, | |||
|
125 | "(", | |||
|
126 | map(m.repr, args).join(", "), | |||
|
127 | ")" | |||
|
128 | ].join(""); | |||
|
129 | }; | |||
|
130 | } | |||
|
131 | return rval; | |||
|
132 | }; | |||
|
133 | ||||
|
134 | /** @id MochiKit.Format.formatLocale */ | |||
|
135 | MochiKit.Format.formatLocale = function (locale) { | |||
|
136 | if (typeof(locale) == "undefined" || locale === null) { | |||
|
137 | locale = "default"; | |||
|
138 | } | |||
|
139 | if (typeof(locale) == "string") { | |||
|
140 | var rval = MochiKit.Format.LOCALE[locale]; | |||
|
141 | if (typeof(rval) == "string") { | |||
|
142 | rval = arguments.callee(rval); | |||
|
143 | MochiKit.Format.LOCALE[locale] = rval; | |||
|
144 | } | |||
|
145 | return rval; | |||
|
146 | } else { | |||
|
147 | return locale; | |||
|
148 | } | |||
|
149 | }; | |||
|
150 | ||||
|
151 | /** @id MochiKit.Format.twoDigitAverage */ | |||
|
152 | MochiKit.Format.twoDigitAverage = function (numerator, denominator) { | |||
|
153 | if (denominator) { | |||
|
154 | var res = numerator / denominator; | |||
|
155 | if (!isNaN(res)) { | |||
|
156 | return MochiKit.Format.twoDigitFloat(numerator / denominator); | |||
|
157 | } | |||
|
158 | } | |||
|
159 | return "0"; | |||
|
160 | }; | |||
|
161 | ||||
|
162 | /** @id MochiKit.Format.twoDigitFloat */ | |||
|
163 | MochiKit.Format.twoDigitFloat = function (someFloat) { | |||
|
164 | var sign = (someFloat < 0 ? '-' : ''); | |||
|
165 | var s = Math.floor(Math.abs(someFloat) * 100).toString(); | |||
|
166 | if (s == '0') { | |||
|
167 | return s; | |||
|
168 | } | |||
|
169 | if (s.length < 3) { | |||
|
170 | while (s.charAt(s.length - 1) == '0') { | |||
|
171 | s = s.substring(0, s.length - 1); | |||
|
172 | } | |||
|
173 | return sign + '0.' + s; | |||
|
174 | } | |||
|
175 | var head = sign + s.substring(0, s.length - 2); | |||
|
176 | var tail = s.substring(s.length - 2, s.length); | |||
|
177 | if (tail == '00') { | |||
|
178 | return head; | |||
|
179 | } else if (tail.charAt(1) == '0') { | |||
|
180 | return head + '.' + tail.charAt(0); | |||
|
181 | } else { | |||
|
182 | return head + '.' + tail; | |||
|
183 | } | |||
|
184 | }; | |||
|
185 | ||||
|
186 | /** @id MochiKit.Format.lstrip */ | |||
|
187 | MochiKit.Format.lstrip = function (str, /* optional */chars) { | |||
|
188 | str = str + ""; | |||
|
189 | if (typeof(str) != "string") { | |||
|
190 | return null; | |||
|
191 | } | |||
|
192 | if (!chars) { | |||
|
193 | return str.replace(/^\s+/, ""); | |||
|
194 | } else { | |||
|
195 | return str.replace(new RegExp("^[" + chars + "]+"), ""); | |||
|
196 | } | |||
|
197 | }; | |||
|
198 | ||||
|
199 | /** @id MochiKit.Format.rstrip */ | |||
|
200 | MochiKit.Format.rstrip = function (str, /* optional */chars) { | |||
|
201 | str = str + ""; | |||
|
202 | if (typeof(str) != "string") { | |||
|
203 | return null; | |||
|
204 | } | |||
|
205 | if (!chars) { | |||
|
206 | return str.replace(/\s+$/, ""); | |||
|
207 | } else { | |||
|
208 | return str.replace(new RegExp("[" + chars + "]+$"), ""); | |||
|
209 | } | |||
|
210 | }; | |||
|
211 | ||||
|
212 | /** @id MochiKit.Format.strip */ | |||
|
213 | MochiKit.Format.strip = function (str, /* optional */chars) { | |||
|
214 | var self = MochiKit.Format; | |||
|
215 | return self.rstrip(self.lstrip(str, chars), chars); | |||
|
216 | }; | |||
|
217 | ||||
|
218 | /** @id MochiKit.Format.truncToFixed */ | |||
|
219 | MochiKit.Format.truncToFixed = function (aNumber, precision) { | |||
|
220 | aNumber = Math.floor(aNumber * Math.pow(10, precision)); | |||
|
221 | var res = (aNumber * Math.pow(10, -precision)).toFixed(precision); | |||
|
222 | if (res.charAt(0) == ".") { | |||
|
223 | res = "0" + res; | |||
|
224 | } | |||
|
225 | return res; | |||
|
226 | }; | |||
|
227 | ||||
|
228 | /** @id MochiKit.Format.roundToFixed */ | |||
|
229 | MochiKit.Format.roundToFixed = function (aNumber, precision) { | |||
|
230 | return MochiKit.Format.truncToFixed( | |||
|
231 | aNumber + 0.5 * Math.pow(10, -precision), | |||
|
232 | precision | |||
|
233 | ); | |||
|
234 | }; | |||
|
235 | ||||
|
236 | /** @id MochiKit.Format.percentFormat */ | |||
|
237 | MochiKit.Format.percentFormat = function (someFloat) { | |||
|
238 | return MochiKit.Format.twoDigitFloat(100 * someFloat) + '%'; | |||
|
239 | }; | |||
|
240 | ||||
|
241 | MochiKit.Format.EXPORT = [ | |||
|
242 | "truncToFixed", | |||
|
243 | "roundToFixed", | |||
|
244 | "numberFormatter", | |||
|
245 | "formatLocale", | |||
|
246 | "twoDigitAverage", | |||
|
247 | "twoDigitFloat", | |||
|
248 | "percentFormat", | |||
|
249 | "lstrip", | |||
|
250 | "rstrip", | |||
|
251 | "strip" | |||
|
252 | ]; | |||
|
253 | ||||
|
254 | MochiKit.Format.LOCALE = { | |||
|
255 | en_US: {separator: ",", decimal: ".", percent: "%"}, | |||
|
256 | de_DE: {separator: ".", decimal: ",", percent: "%"}, | |||
|
257 | pt_BR: {separator: ".", decimal: ",", percent: "%"}, | |||
|
258 | fr_FR: {separator: " ", decimal: ",", percent: "%"}, | |||
|
259 | "default": "en_US" | |||
|
260 | }; | |||
|
261 | ||||
|
262 | MochiKit.Format.EXPORT_OK = []; | |||
|
263 | MochiKit.Format.EXPORT_TAGS = { | |||
|
264 | ':all': MochiKit.Format.EXPORT, | |||
|
265 | ':common': MochiKit.Format.EXPORT | |||
|
266 | }; | |||
|
267 | ||||
|
268 | MochiKit.Format.__new__ = function () { | |||
|
269 | // MochiKit.Base.nameFunctions(this); | |||
|
270 | var base = this.NAME + "."; | |||
|
271 | var k, v, o; | |||
|
272 | for (k in this.LOCALE) { | |||
|
273 | o = this.LOCALE[k]; | |||
|
274 | if (typeof(o) == "object") { | |||
|
275 | o.repr = function () { return this.NAME; }; | |||
|
276 | o.NAME = base + "LOCALE." + k; | |||
|
277 | } | |||
|
278 | } | |||
|
279 | for (k in this) { | |||
|
280 | o = this[k]; | |||
|
281 | if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') { | |||
|
282 | try { | |||
|
283 | o.NAME = base + k; | |||
|
284 | } catch (e) { | |||
|
285 | // pass | |||
|
286 | } | |||
|
287 | } | |||
|
288 | } | |||
|
289 | }; | |||
|
290 | ||||
|
291 | MochiKit.Format.__new__(); | |||
|
292 | ||||
|
293 | if (typeof(MochiKit.Base) != "undefined") { | |||
|
294 | MochiKit.Base._exportSymbols(this, MochiKit.Format); | |||
|
295 | } else { | |||
|
296 | (function (globals, module) { | |||
|
297 | if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined') | |||
|
298 | || (MochiKit.__export__ === false)) { | |||
|
299 | var all = module.EXPORT_TAGS[":all"]; | |||
|
300 | for (var i = 0; i < all.length; i++) { | |||
|
301 | globals[all[i]] = module[all[i]]; | |||
|
302 | } | |||
|
303 | } | |||
|
304 | })(this, MochiKit.Format); | |||
|
305 | } |
This diff has been collapsed as it changes many lines, (851 lines changed) Show them Hide them | |||||
@@ -0,0 +1,851 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.Iter 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.Iter'); | |||
|
13 | dojo.require('MochiKit.Base'); | |||
|
14 | } | |||
|
15 | ||||
|
16 | if (typeof(JSAN) != 'undefined') { | |||
|
17 | JSAN.use("MochiKit.Base", []); | |||
|
18 | } | |||
|
19 | ||||
|
20 | try { | |||
|
21 | if (typeof(MochiKit.Base) == 'undefined') { | |||
|
22 | throw ""; | |||
|
23 | } | |||
|
24 | } catch (e) { | |||
|
25 | throw "MochiKit.Iter depends on MochiKit.Base!"; | |||
|
26 | } | |||
|
27 | ||||
|
28 | if (typeof(MochiKit.Iter) == 'undefined') { | |||
|
29 | MochiKit.Iter = {}; | |||
|
30 | } | |||
|
31 | ||||
|
32 | MochiKit.Iter.NAME = "MochiKit.Iter"; | |||
|
33 | MochiKit.Iter.VERSION = "1.4"; | |||
|
34 | MochiKit.Base.update(MochiKit.Iter, { | |||
|
35 | __repr__: function () { | |||
|
36 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
37 | }, | |||
|
38 | toString: function () { | |||
|
39 | return this.__repr__(); | |||
|
40 | }, | |||
|
41 | ||||
|
42 | /** @id MochiKit.Iter.registerIteratorFactory */ | |||
|
43 | registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) { | |||
|
44 | MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override); | |||
|
45 | }, | |||
|
46 | ||||
|
47 | /** @id MochiKit.Iter.iter */ | |||
|
48 | iter: function (iterable, /* optional */ sentinel) { | |||
|
49 | var self = MochiKit.Iter; | |||
|
50 | if (arguments.length == 2) { | |||
|
51 | return self.takewhile( | |||
|
52 | function (a) { return a != sentinel; }, | |||
|
53 | iterable | |||
|
54 | ); | |||
|
55 | } | |||
|
56 | if (typeof(iterable.next) == 'function') { | |||
|
57 | return iterable; | |||
|
58 | } else if (typeof(iterable.iter) == 'function') { | |||
|
59 | return iterable.iter(); | |||
|
60 | /* | |||
|
61 | } else if (typeof(iterable.__iterator__) == 'function') { | |||
|
62 | // | |||
|
63 | // XXX: We can't support JavaScript 1.7 __iterator__ directly | |||
|
64 | // because of Object.prototype.__iterator__ | |||
|
65 | // | |||
|
66 | return iterable.__iterator__(); | |||
|
67 | */ | |||
|
68 | } | |||
|
69 | ||||
|
70 | try { | |||
|
71 | return self.iteratorRegistry.match(iterable); | |||
|
72 | } catch (e) { | |||
|
73 | var m = MochiKit.Base; | |||
|
74 | if (e == m.NotFound) { | |||
|
75 | e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable"); | |||
|
76 | } | |||
|
77 | throw e; | |||
|
78 | } | |||
|
79 | }, | |||
|
80 | ||||
|
81 | /** @id MochiKit.Iter.count */ | |||
|
82 | count: function (n) { | |||
|
83 | if (!n) { | |||
|
84 | n = 0; | |||
|
85 | } | |||
|
86 | var m = MochiKit.Base; | |||
|
87 | return { | |||
|
88 | repr: function () { return "count(" + n + ")"; }, | |||
|
89 | toString: m.forwardCall("repr"), | |||
|
90 | next: m.counter(n) | |||
|
91 | }; | |||
|
92 | }, | |||
|
93 | ||||
|
94 | /** @id MochiKit.Iter.cycle */ | |||
|
95 | cycle: function (p) { | |||
|
96 | var self = MochiKit.Iter; | |||
|
97 | var m = MochiKit.Base; | |||
|
98 | var lst = []; | |||
|
99 | var iterator = self.iter(p); | |||
|
100 | return { | |||
|
101 | repr: function () { return "cycle(...)"; }, | |||
|
102 | toString: m.forwardCall("repr"), | |||
|
103 | next: function () { | |||
|
104 | try { | |||
|
105 | var rval = iterator.next(); | |||
|
106 | lst.push(rval); | |||
|
107 | return rval; | |||
|
108 | } catch (e) { | |||
|
109 | if (e != self.StopIteration) { | |||
|
110 | throw e; | |||
|
111 | } | |||
|
112 | if (lst.length === 0) { | |||
|
113 | this.next = function () { | |||
|
114 | throw self.StopIteration; | |||
|
115 | }; | |||
|
116 | } else { | |||
|
117 | var i = -1; | |||
|
118 | this.next = function () { | |||
|
119 | i = (i + 1) % lst.length; | |||
|
120 | return lst[i]; | |||
|
121 | }; | |||
|
122 | } | |||
|
123 | return this.next(); | |||
|
124 | } | |||
|
125 | } | |||
|
126 | }; | |||
|
127 | }, | |||
|
128 | ||||
|
129 | /** @id MochiKit.Iter.repeat */ | |||
|
130 | repeat: function (elem, /* optional */n) { | |||
|
131 | var m = MochiKit.Base; | |||
|
132 | if (typeof(n) == 'undefined') { | |||
|
133 | return { | |||
|
134 | repr: function () { | |||
|
135 | return "repeat(" + m.repr(elem) + ")"; | |||
|
136 | }, | |||
|
137 | toString: m.forwardCall("repr"), | |||
|
138 | next: function () { | |||
|
139 | return elem; | |||
|
140 | } | |||
|
141 | }; | |||
|
142 | } | |||
|
143 | return { | |||
|
144 | repr: function () { | |||
|
145 | return "repeat(" + m.repr(elem) + ", " + n + ")"; | |||
|
146 | }, | |||
|
147 | toString: m.forwardCall("repr"), | |||
|
148 | next: function () { | |||
|
149 | if (n <= 0) { | |||
|
150 | throw MochiKit.Iter.StopIteration; | |||
|
151 | } | |||
|
152 | n -= 1; | |||
|
153 | return elem; | |||
|
154 | } | |||
|
155 | }; | |||
|
156 | }, | |||
|
157 | ||||
|
158 | /** @id MochiKit.Iter.next */ | |||
|
159 | next: function (iterator) { | |||
|
160 | return iterator.next(); | |||
|
161 | }, | |||
|
162 | ||||
|
163 | /** @id MochiKit.Iter.izip */ | |||
|
164 | izip: function (p, q/*, ...*/) { | |||
|
165 | var m = MochiKit.Base; | |||
|
166 | var self = MochiKit.Iter; | |||
|
167 | var next = self.next; | |||
|
168 | var iterables = m.map(self.iter, arguments); | |||
|
169 | return { | |||
|
170 | repr: function () { return "izip(...)"; }, | |||
|
171 | toString: m.forwardCall("repr"), | |||
|
172 | next: function () { return m.map(next, iterables); } | |||
|
173 | }; | |||
|
174 | }, | |||
|
175 | ||||
|
176 | /** @id MochiKit.Iter.ifilter */ | |||
|
177 | ifilter: function (pred, seq) { | |||
|
178 | var m = MochiKit.Base; | |||
|
179 | seq = MochiKit.Iter.iter(seq); | |||
|
180 | if (pred === null) { | |||
|
181 | pred = m.operator.truth; | |||
|
182 | } | |||
|
183 | return { | |||
|
184 | repr: function () { return "ifilter(...)"; }, | |||
|
185 | toString: m.forwardCall("repr"), | |||
|
186 | next: function () { | |||
|
187 | while (true) { | |||
|
188 | var rval = seq.next(); | |||
|
189 | if (pred(rval)) { | |||
|
190 | return rval; | |||
|
191 | } | |||
|
192 | } | |||
|
193 | // mozilla warnings aren't too bright | |||
|
194 | return undefined; | |||
|
195 | } | |||
|
196 | }; | |||
|
197 | }, | |||
|
198 | ||||
|
199 | /** @id MochiKit.Iter.ifilterfalse */ | |||
|
200 | ifilterfalse: function (pred, seq) { | |||
|
201 | var m = MochiKit.Base; | |||
|
202 | seq = MochiKit.Iter.iter(seq); | |||
|
203 | if (pred === null) { | |||
|
204 | pred = m.operator.truth; | |||
|
205 | } | |||
|
206 | return { | |||
|
207 | repr: function () { return "ifilterfalse(...)"; }, | |||
|
208 | toString: m.forwardCall("repr"), | |||
|
209 | next: function () { | |||
|
210 | while (true) { | |||
|
211 | var rval = seq.next(); | |||
|
212 | if (!pred(rval)) { | |||
|
213 | return rval; | |||
|
214 | } | |||
|
215 | } | |||
|
216 | // mozilla warnings aren't too bright | |||
|
217 | return undefined; | |||
|
218 | } | |||
|
219 | }; | |||
|
220 | }, | |||
|
221 | ||||
|
222 | /** @id MochiKit.Iter.islice */ | |||
|
223 | islice: function (seq/*, [start,] stop[, step] */) { | |||
|
224 | var self = MochiKit.Iter; | |||
|
225 | var m = MochiKit.Base; | |||
|
226 | seq = self.iter(seq); | |||
|
227 | var start = 0; | |||
|
228 | var stop = 0; | |||
|
229 | var step = 1; | |||
|
230 | var i = -1; | |||
|
231 | if (arguments.length == 2) { | |||
|
232 | stop = arguments[1]; | |||
|
233 | } else if (arguments.length == 3) { | |||
|
234 | start = arguments[1]; | |||
|
235 | stop = arguments[2]; | |||
|
236 | } else { | |||
|
237 | start = arguments[1]; | |||
|
238 | stop = arguments[2]; | |||
|
239 | step = arguments[3]; | |||
|
240 | } | |||
|
241 | return { | |||
|
242 | repr: function () { | |||
|
243 | return "islice(" + ["...", start, stop, step].join(", ") + ")"; | |||
|
244 | }, | |||
|
245 | toString: m.forwardCall("repr"), | |||
|
246 | next: function () { | |||
|
247 | var rval; | |||
|
248 | while (i < start) { | |||
|
249 | rval = seq.next(); | |||
|
250 | i++; | |||
|
251 | } | |||
|
252 | if (start >= stop) { | |||
|
253 | throw self.StopIteration; | |||
|
254 | } | |||
|
255 | start += step; | |||
|
256 | return rval; | |||
|
257 | } | |||
|
258 | }; | |||
|
259 | }, | |||
|
260 | ||||
|
261 | /** @id MochiKit.Iter.imap */ | |||
|
262 | imap: function (fun, p, q/*, ...*/) { | |||
|
263 | var m = MochiKit.Base; | |||
|
264 | var self = MochiKit.Iter; | |||
|
265 | var iterables = m.map(self.iter, m.extend(null, arguments, 1)); | |||
|
266 | var map = m.map; | |||
|
267 | var next = self.next; | |||
|
268 | return { | |||
|
269 | repr: function () { return "imap(...)"; }, | |||
|
270 | toString: m.forwardCall("repr"), | |||
|
271 | next: function () { | |||
|
272 | return fun.apply(this, map(next, iterables)); | |||
|
273 | } | |||
|
274 | }; | |||
|
275 | }, | |||
|
276 | ||||
|
277 | /** @id MochiKit.Iter.applymap */ | |||
|
278 | applymap: function (fun, seq, self) { | |||
|
279 | seq = MochiKit.Iter.iter(seq); | |||
|
280 | var m = MochiKit.Base; | |||
|
281 | return { | |||
|
282 | repr: function () { return "applymap(...)"; }, | |||
|
283 | toString: m.forwardCall("repr"), | |||
|
284 | next: function () { | |||
|
285 | return fun.apply(self, seq.next()); | |||
|
286 | } | |||
|
287 | }; | |||
|
288 | }, | |||
|
289 | ||||
|
290 | /** @id MochiKit.Iter.chain */ | |||
|
291 | chain: function (p, q/*, ...*/) { | |||
|
292 | // dumb fast path | |||
|
293 | var self = MochiKit.Iter; | |||
|
294 | var m = MochiKit.Base; | |||
|
295 | if (arguments.length == 1) { | |||
|
296 | return self.iter(arguments[0]); | |||
|
297 | } | |||
|
298 | var argiter = m.map(self.iter, arguments); | |||
|
299 | return { | |||
|
300 | repr: function () { return "chain(...)"; }, | |||
|
301 | toString: m.forwardCall("repr"), | |||
|
302 | next: function () { | |||
|
303 | while (argiter.length > 1) { | |||
|
304 | try { | |||
|
305 | return argiter[0].next(); | |||
|
306 | } catch (e) { | |||
|
307 | if (e != self.StopIteration) { | |||
|
308 | throw e; | |||
|
309 | } | |||
|
310 | argiter.shift(); | |||
|
311 | } | |||
|
312 | } | |||
|
313 | if (argiter.length == 1) { | |||
|
314 | // optimize last element | |||
|
315 | var arg = argiter.shift(); | |||
|
316 | this.next = m.bind("next", arg); | |||
|
317 | return this.next(); | |||
|
318 | } | |||
|
319 | throw self.StopIteration; | |||
|
320 | } | |||
|
321 | }; | |||
|
322 | }, | |||
|
323 | ||||
|
324 | /** @id MochiKit.Iter.takewhile */ | |||
|
325 | takewhile: function (pred, seq) { | |||
|
326 | var self = MochiKit.Iter; | |||
|
327 | seq = self.iter(seq); | |||
|
328 | return { | |||
|
329 | repr: function () { return "takewhile(...)"; }, | |||
|
330 | toString: MochiKit.Base.forwardCall("repr"), | |||
|
331 | next: function () { | |||
|
332 | var rval = seq.next(); | |||
|
333 | if (!pred(rval)) { | |||
|
334 | this.next = function () { | |||
|
335 | throw self.StopIteration; | |||
|
336 | }; | |||
|
337 | this.next(); | |||
|
338 | } | |||
|
339 | return rval; | |||
|
340 | } | |||
|
341 | }; | |||
|
342 | }, | |||
|
343 | ||||
|
344 | /** @id MochiKit.Iter.dropwhile */ | |||
|
345 | dropwhile: function (pred, seq) { | |||
|
346 | seq = MochiKit.Iter.iter(seq); | |||
|
347 | var m = MochiKit.Base; | |||
|
348 | var bind = m.bind; | |||
|
349 | return { | |||
|
350 | "repr": function () { return "dropwhile(...)"; }, | |||
|
351 | "toString": m.forwardCall("repr"), | |||
|
352 | "next": function () { | |||
|
353 | while (true) { | |||
|
354 | var rval = seq.next(); | |||
|
355 | if (!pred(rval)) { | |||
|
356 | break; | |||
|
357 | } | |||
|
358 | } | |||
|
359 | this.next = bind("next", seq); | |||
|
360 | return rval; | |||
|
361 | } | |||
|
362 | }; | |||
|
363 | }, | |||
|
364 | ||||
|
365 | _tee: function (ident, sync, iterable) { | |||
|
366 | sync.pos[ident] = -1; | |||
|
367 | var m = MochiKit.Base; | |||
|
368 | var listMin = m.listMin; | |||
|
369 | return { | |||
|
370 | repr: function () { return "tee(" + ident + ", ...)"; }, | |||
|
371 | toString: m.forwardCall("repr"), | |||
|
372 | next: function () { | |||
|
373 | var rval; | |||
|
374 | var i = sync.pos[ident]; | |||
|
375 | ||||
|
376 | if (i == sync.max) { | |||
|
377 | rval = iterable.next(); | |||
|
378 | sync.deque.push(rval); | |||
|
379 | sync.max += 1; | |||
|
380 | sync.pos[ident] += 1; | |||
|
381 | } else { | |||
|
382 | rval = sync.deque[i - sync.min]; | |||
|
383 | sync.pos[ident] += 1; | |||
|
384 | if (i == sync.min && listMin(sync.pos) != sync.min) { | |||
|
385 | sync.min += 1; | |||
|
386 | sync.deque.shift(); | |||
|
387 | } | |||
|
388 | } | |||
|
389 | return rval; | |||
|
390 | } | |||
|
391 | }; | |||
|
392 | }, | |||
|
393 | ||||
|
394 | /** @id MochiKit.Iter.tee */ | |||
|
395 | tee: function (iterable, n/* = 2 */) { | |||
|
396 | var rval = []; | |||
|
397 | var sync = { | |||
|
398 | "pos": [], | |||
|
399 | "deque": [], | |||
|
400 | "max": -1, | |||
|
401 | "min": -1 | |||
|
402 | }; | |||
|
403 | if (arguments.length == 1 || typeof(n) == "undefined" || n === null) { | |||
|
404 | n = 2; | |||
|
405 | } | |||
|
406 | var self = MochiKit.Iter; | |||
|
407 | iterable = self.iter(iterable); | |||
|
408 | var _tee = self._tee; | |||
|
409 | for (var i = 0; i < n; i++) { | |||
|
410 | rval.push(_tee(i, sync, iterable)); | |||
|
411 | } | |||
|
412 | return rval; | |||
|
413 | }, | |||
|
414 | ||||
|
415 | /** @id MochiKit.Iter.list */ | |||
|
416 | list: function (iterable) { | |||
|
417 | // Fast-path for Array and Array-like | |||
|
418 | var rval; | |||
|
419 | if (iterable instanceof Array) { | |||
|
420 | return iterable.slice(); | |||
|
421 | } | |||
|
422 | // this is necessary to avoid a Safari crash | |||
|
423 | if (typeof(iterable) == "function" && | |||
|
424 | !(iterable instanceof Function) && | |||
|
425 | typeof(iterable.length) == 'number') { | |||
|
426 | rval = []; | |||
|
427 | for (var i = 0; i < iterable.length; i++) { | |||
|
428 | rval.push(iterable[i]); | |||
|
429 | } | |||
|
430 | return rval; | |||
|
431 | } | |||
|
432 | ||||
|
433 | var self = MochiKit.Iter; | |||
|
434 | iterable = self.iter(iterable); | |||
|
435 | var rval = []; | |||
|
436 | try { | |||
|
437 | while (true) { | |||
|
438 | rval.push(iterable.next()); | |||
|
439 | } | |||
|
440 | } catch (e) { | |||
|
441 | if (e != self.StopIteration) { | |||
|
442 | throw e; | |||
|
443 | } | |||
|
444 | return rval; | |||
|
445 | } | |||
|
446 | // mozilla warnings aren't too bright | |||
|
447 | return undefined; | |||
|
448 | }, | |||
|
449 | ||||
|
450 | ||||
|
451 | /** @id MochiKit.Iter.reduce */ | |||
|
452 | reduce: function (fn, iterable, /* optional */initial) { | |||
|
453 | var i = 0; | |||
|
454 | var x = initial; | |||
|
455 | var self = MochiKit.Iter; | |||
|
456 | iterable = self.iter(iterable); | |||
|
457 | if (arguments.length < 3) { | |||
|
458 | try { | |||
|
459 | x = iterable.next(); | |||
|
460 | } catch (e) { | |||
|
461 | if (e == self.StopIteration) { | |||
|
462 | e = new TypeError("reduce() of empty sequence with no initial value"); | |||
|
463 | } | |||
|
464 | throw e; | |||
|
465 | } | |||
|
466 | i++; | |||
|
467 | } | |||
|
468 | try { | |||
|
469 | while (true) { | |||
|
470 | x = fn(x, iterable.next()); | |||
|
471 | } | |||
|
472 | } catch (e) { | |||
|
473 | if (e != self.StopIteration) { | |||
|
474 | throw e; | |||
|
475 | } | |||
|
476 | } | |||
|
477 | return x; | |||
|
478 | }, | |||
|
479 | ||||
|
480 | /** @id MochiKit.Iter.range */ | |||
|
481 | range: function (/* [start,] stop[, step] */) { | |||
|
482 | var start = 0; | |||
|
483 | var stop = 0; | |||
|
484 | var step = 1; | |||
|
485 | if (arguments.length == 1) { | |||
|
486 | stop = arguments[0]; | |||
|
487 | } else if (arguments.length == 2) { | |||
|
488 | start = arguments[0]; | |||
|
489 | stop = arguments[1]; | |||
|
490 | } else if (arguments.length == 3) { | |||
|
491 | start = arguments[0]; | |||
|
492 | stop = arguments[1]; | |||
|
493 | step = arguments[2]; | |||
|
494 | } else { | |||
|
495 | throw new TypeError("range() takes 1, 2, or 3 arguments!"); | |||
|
496 | } | |||
|
497 | if (step === 0) { | |||
|
498 | throw new TypeError("range() step must not be 0"); | |||
|
499 | } | |||
|
500 | return { | |||
|
501 | next: function () { | |||
|
502 | if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) { | |||
|
503 | throw MochiKit.Iter.StopIteration; | |||
|
504 | } | |||
|
505 | var rval = start; | |||
|
506 | start += step; | |||
|
507 | return rval; | |||
|
508 | }, | |||
|
509 | repr: function () { | |||
|
510 | return "range(" + [start, stop, step].join(", ") + ")"; | |||
|
511 | }, | |||
|
512 | toString: MochiKit.Base.forwardCall("repr") | |||
|
513 | }; | |||
|
514 | }, | |||
|
515 | ||||
|
516 | /** @id MochiKit.Iter.sum */ | |||
|
517 | sum: function (iterable, start/* = 0 */) { | |||
|
518 | if (typeof(start) == "undefined" || start === null) { | |||
|
519 | start = 0; | |||
|
520 | } | |||
|
521 | var x = start; | |||
|
522 | var self = MochiKit.Iter; | |||
|
523 | iterable = self.iter(iterable); | |||
|
524 | try { | |||
|
525 | while (true) { | |||
|
526 | x += iterable.next(); | |||
|
527 | } | |||
|
528 | } catch (e) { | |||
|
529 | if (e != self.StopIteration) { | |||
|
530 | throw e; | |||
|
531 | } | |||
|
532 | } | |||
|
533 | return x; | |||
|
534 | }, | |||
|
535 | ||||
|
536 | /** @id MochiKit.Iter.exhaust */ | |||
|
537 | exhaust: function (iterable) { | |||
|
538 | var self = MochiKit.Iter; | |||
|
539 | iterable = self.iter(iterable); | |||
|
540 | try { | |||
|
541 | while (true) { | |||
|
542 | iterable.next(); | |||
|
543 | } | |||
|
544 | } catch (e) { | |||
|
545 | if (e != self.StopIteration) { | |||
|
546 | throw e; | |||
|
547 | } | |||
|
548 | } | |||
|
549 | }, | |||
|
550 | ||||
|
551 | /** @id MochiKit.Iter.forEach */ | |||
|
552 | forEach: function (iterable, func, /* optional */self) { | |||
|
553 | var m = MochiKit.Base; | |||
|
554 | if (arguments.length > 2) { | |||
|
555 | func = m.bind(func, self); | |||
|
556 | } | |||
|
557 | // fast path for array | |||
|
558 | if (m.isArrayLike(iterable)) { | |||
|
559 | try { | |||
|
560 | for (var i = 0; i < iterable.length; i++) { | |||
|
561 | func(iterable[i]); | |||
|
562 | } | |||
|
563 | } catch (e) { | |||
|
564 | if (e != MochiKit.Iter.StopIteration) { | |||
|
565 | throw e; | |||
|
566 | } | |||
|
567 | } | |||
|
568 | } else { | |||
|
569 | self = MochiKit.Iter; | |||
|
570 | self.exhaust(self.imap(func, iterable)); | |||
|
571 | } | |||
|
572 | }, | |||
|
573 | ||||
|
574 | /** @id MochiKit.Iter.every */ | |||
|
575 | every: function (iterable, func) { | |||
|
576 | var self = MochiKit.Iter; | |||
|
577 | try { | |||
|
578 | self.ifilterfalse(func, iterable).next(); | |||
|
579 | return false; | |||
|
580 | } catch (e) { | |||
|
581 | if (e != self.StopIteration) { | |||
|
582 | throw e; | |||
|
583 | } | |||
|
584 | return true; | |||
|
585 | } | |||
|
586 | }, | |||
|
587 | ||||
|
588 | /** @id MochiKit.Iter.sorted */ | |||
|
589 | sorted: function (iterable, /* optional */cmp) { | |||
|
590 | var rval = MochiKit.Iter.list(iterable); | |||
|
591 | if (arguments.length == 1) { | |||
|
592 | cmp = MochiKit.Base.compare; | |||
|
593 | } | |||
|
594 | rval.sort(cmp); | |||
|
595 | return rval; | |||
|
596 | }, | |||
|
597 | ||||
|
598 | /** @id MochiKit.Iter.reversed */ | |||
|
599 | reversed: function (iterable) { | |||
|
600 | var rval = MochiKit.Iter.list(iterable); | |||
|
601 | rval.reverse(); | |||
|
602 | return rval; | |||
|
603 | }, | |||
|
604 | ||||
|
605 | /** @id MochiKit.Iter.some */ | |||
|
606 | some: function (iterable, func) { | |||
|
607 | var self = MochiKit.Iter; | |||
|
608 | try { | |||
|
609 | self.ifilter(func, iterable).next(); | |||
|
610 | return true; | |||
|
611 | } catch (e) { | |||
|
612 | if (e != self.StopIteration) { | |||
|
613 | throw e; | |||
|
614 | } | |||
|
615 | return false; | |||
|
616 | } | |||
|
617 | }, | |||
|
618 | ||||
|
619 | /** @id MochiKit.Iter.iextend */ | |||
|
620 | iextend: function (lst, iterable) { | |||
|
621 | if (MochiKit.Base.isArrayLike(iterable)) { | |||
|
622 | // fast-path for array-like | |||
|
623 | for (var i = 0; i < iterable.length; i++) { | |||
|
624 | lst.push(iterable[i]); | |||
|
625 | } | |||
|
626 | } else { | |||
|
627 | var self = MochiKit.Iter; | |||
|
628 | iterable = self.iter(iterable); | |||
|
629 | try { | |||
|
630 | while (true) { | |||
|
631 | lst.push(iterable.next()); | |||
|
632 | } | |||
|
633 | } catch (e) { | |||
|
634 | if (e != self.StopIteration) { | |||
|
635 | throw e; | |||
|
636 | } | |||
|
637 | } | |||
|
638 | } | |||
|
639 | return lst; | |||
|
640 | }, | |||
|
641 | ||||
|
642 | /** @id MochiKit.Iter.groupby */ | |||
|
643 | groupby: function(iterable, /* optional */ keyfunc) { | |||
|
644 | var m = MochiKit.Base; | |||
|
645 | var self = MochiKit.Iter; | |||
|
646 | if (arguments.length < 2) { | |||
|
647 | keyfunc = m.operator.identity; | |||
|
648 | } | |||
|
649 | iterable = self.iter(iterable); | |||
|
650 | ||||
|
651 | // shared | |||
|
652 | var pk = undefined; | |||
|
653 | var k = undefined; | |||
|
654 | var v; | |||
|
655 | ||||
|
656 | function fetch() { | |||
|
657 | v = iterable.next(); | |||
|
658 | k = keyfunc(v); | |||
|
659 | }; | |||
|
660 | ||||
|
661 | function eat() { | |||
|
662 | var ret = v; | |||
|
663 | v = undefined; | |||
|
664 | return ret; | |||
|
665 | }; | |||
|
666 | ||||
|
667 | var first = true; | |||
|
668 | var compare = m.compare; | |||
|
669 | return { | |||
|
670 | repr: function () { return "groupby(...)"; }, | |||
|
671 | next: function() { | |||
|
672 | // iterator-next | |||
|
673 | ||||
|
674 | // iterate until meet next group | |||
|
675 | while (compare(k, pk) === 0) { | |||
|
676 | fetch(); | |||
|
677 | if (first) { | |||
|
678 | first = false; | |||
|
679 | break; | |||
|
680 | } | |||
|
681 | } | |||
|
682 | pk = k; | |||
|
683 | return [k, { | |||
|
684 | next: function() { | |||
|
685 | // subiterator-next | |||
|
686 | if (v == undefined) { // Is there something to eat? | |||
|
687 | fetch(); | |||
|
688 | } | |||
|
689 | if (compare(k, pk) !== 0) { | |||
|
690 | throw self.StopIteration; | |||
|
691 | } | |||
|
692 | return eat(); | |||
|
693 | } | |||
|
694 | }]; | |||
|
695 | } | |||
|
696 | }; | |||
|
697 | }, | |||
|
698 | ||||
|
699 | /** @id MochiKit.Iter.groupby_as_array */ | |||
|
700 | groupby_as_array: function (iterable, /* optional */ keyfunc) { | |||
|
701 | var m = MochiKit.Base; | |||
|
702 | var self = MochiKit.Iter; | |||
|
703 | if (arguments.length < 2) { | |||
|
704 | keyfunc = m.operator.identity; | |||
|
705 | } | |||
|
706 | ||||
|
707 | iterable = self.iter(iterable); | |||
|
708 | var result = []; | |||
|
709 | var first = true; | |||
|
710 | var prev_key; | |||
|
711 | var compare = m.compare; | |||
|
712 | while (true) { | |||
|
713 | try { | |||
|
714 | var value = iterable.next(); | |||
|
715 | var key = keyfunc(value); | |||
|
716 | } catch (e) { | |||
|
717 | if (e == self.StopIteration) { | |||
|
718 | break; | |||
|
719 | } | |||
|
720 | throw e; | |||
|
721 | } | |||
|
722 | if (first || compare(key, prev_key) !== 0) { | |||
|
723 | var values = []; | |||
|
724 | result.push([key, values]); | |||
|
725 | } | |||
|
726 | values.push(value); | |||
|
727 | first = false; | |||
|
728 | prev_key = key; | |||
|
729 | } | |||
|
730 | return result; | |||
|
731 | }, | |||
|
732 | ||||
|
733 | /** @id MochiKit.Iter.arrayLikeIter */ | |||
|
734 | arrayLikeIter: function (iterable) { | |||
|
735 | var i = 0; | |||
|
736 | return { | |||
|
737 | repr: function () { return "arrayLikeIter(...)"; }, | |||
|
738 | toString: MochiKit.Base.forwardCall("repr"), | |||
|
739 | next: function () { | |||
|
740 | if (i >= iterable.length) { | |||
|
741 | throw MochiKit.Iter.StopIteration; | |||
|
742 | } | |||
|
743 | return iterable[i++]; | |||
|
744 | } | |||
|
745 | }; | |||
|
746 | }, | |||
|
747 | ||||
|
748 | /** @id MochiKit.Iter.hasIterateNext */ | |||
|
749 | hasIterateNext: function (iterable) { | |||
|
750 | return (iterable && typeof(iterable.iterateNext) == "function"); | |||
|
751 | }, | |||
|
752 | ||||
|
753 | /** @id MochiKit.Iter.iterateNextIter */ | |||
|
754 | iterateNextIter: function (iterable) { | |||
|
755 | return { | |||
|
756 | repr: function () { return "iterateNextIter(...)"; }, | |||
|
757 | toString: MochiKit.Base.forwardCall("repr"), | |||
|
758 | next: function () { | |||
|
759 | var rval = iterable.iterateNext(); | |||
|
760 | if (rval === null || rval === undefined) { | |||
|
761 | throw MochiKit.Iter.StopIteration; | |||
|
762 | } | |||
|
763 | return rval; | |||
|
764 | } | |||
|
765 | }; | |||
|
766 | } | |||
|
767 | }); | |||
|
768 | ||||
|
769 | ||||
|
770 | MochiKit.Iter.EXPORT_OK = [ | |||
|
771 | "iteratorRegistry", | |||
|
772 | "arrayLikeIter", | |||
|
773 | "hasIterateNext", | |||
|
774 | "iterateNextIter" | |||
|
775 | ]; | |||
|
776 | ||||
|
777 | MochiKit.Iter.EXPORT = [ | |||
|
778 | "StopIteration", | |||
|
779 | "registerIteratorFactory", | |||
|
780 | "iter", | |||
|
781 | "count", | |||
|
782 | "cycle", | |||
|
783 | "repeat", | |||
|
784 | "next", | |||
|
785 | "izip", | |||
|
786 | "ifilter", | |||
|
787 | "ifilterfalse", | |||
|
788 | "islice", | |||
|
789 | "imap", | |||
|
790 | "applymap", | |||
|
791 | "chain", | |||
|
792 | "takewhile", | |||
|
793 | "dropwhile", | |||
|
794 | "tee", | |||
|
795 | "list", | |||
|
796 | "reduce", | |||
|
797 | "range", | |||
|
798 | "sum", | |||
|
799 | "exhaust", | |||
|
800 | "forEach", | |||
|
801 | "every", | |||
|
802 | "sorted", | |||
|
803 | "reversed", | |||
|
804 | "some", | |||
|
805 | "iextend", | |||
|
806 | "groupby", | |||
|
807 | "groupby_as_array" | |||
|
808 | ]; | |||
|
809 | ||||
|
810 | MochiKit.Iter.__new__ = function () { | |||
|
811 | var m = MochiKit.Base; | |||
|
812 | // Re-use StopIteration if exists (e.g. SpiderMonkey) | |||
|
813 | if (typeof(StopIteration) != "undefined") { | |||
|
814 | this.StopIteration = StopIteration; | |||
|
815 | } else { | |||
|
816 | /** @id MochiKit.Iter.StopIteration */ | |||
|
817 | this.StopIteration = new m.NamedError("StopIteration"); | |||
|
818 | } | |||
|
819 | this.iteratorRegistry = new m.AdapterRegistry(); | |||
|
820 | // Register the iterator factory for arrays | |||
|
821 | this.registerIteratorFactory( | |||
|
822 | "arrayLike", | |||
|
823 | m.isArrayLike, | |||
|
824 | this.arrayLikeIter | |||
|
825 | ); | |||
|
826 | ||||
|
827 | this.registerIteratorFactory( | |||
|
828 | "iterateNext", | |||
|
829 | this.hasIterateNext, | |||
|
830 | this.iterateNextIter | |||
|
831 | ); | |||
|
832 | ||||
|
833 | this.EXPORT_TAGS = { | |||
|
834 | ":common": this.EXPORT, | |||
|
835 | ":all": m.concat(this.EXPORT, this.EXPORT_OK) | |||
|
836 | }; | |||
|
837 | ||||
|
838 | m.nameFunctions(this); | |||
|
839 | ||||
|
840 | }; | |||
|
841 | ||||
|
842 | MochiKit.Iter.__new__(); | |||
|
843 | ||||
|
844 | // | |||
|
845 | // XXX: Internet Explorer blows | |||
|
846 | // | |||
|
847 | if (MochiKit.__export__) { | |||
|
848 | reduce = MochiKit.Iter.reduce; | |||
|
849 | } | |||
|
850 | ||||
|
851 | MochiKit.Base._exportSymbols(this, MochiKit.Iter); |
@@ -0,0 +1,321 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.Logging 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.Logging'); | |||
|
13 | dojo.require('MochiKit.Base'); | |||
|
14 | } | |||
|
15 | ||||
|
16 | if (typeof(JSAN) != 'undefined') { | |||
|
17 | JSAN.use("MochiKit.Base", []); | |||
|
18 | } | |||
|
19 | ||||
|
20 | try { | |||
|
21 | if (typeof(MochiKit.Base) == 'undefined') { | |||
|
22 | throw ""; | |||
|
23 | } | |||
|
24 | } catch (e) { | |||
|
25 | throw "MochiKit.Logging depends on MochiKit.Base!"; | |||
|
26 | } | |||
|
27 | ||||
|
28 | if (typeof(MochiKit.Logging) == 'undefined') { | |||
|
29 | MochiKit.Logging = {}; | |||
|
30 | } | |||
|
31 | ||||
|
32 | MochiKit.Logging.NAME = "MochiKit.Logging"; | |||
|
33 | MochiKit.Logging.VERSION = "1.4"; | |||
|
34 | MochiKit.Logging.__repr__ = function () { | |||
|
35 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
36 | }; | |||
|
37 | ||||
|
38 | MochiKit.Logging.toString = function () { | |||
|
39 | return this.__repr__(); | |||
|
40 | }; | |||
|
41 | ||||
|
42 | ||||
|
43 | MochiKit.Logging.EXPORT = [ | |||
|
44 | "LogLevel", | |||
|
45 | "LogMessage", | |||
|
46 | "Logger", | |||
|
47 | "alertListener", | |||
|
48 | "logger", | |||
|
49 | "log", | |||
|
50 | "logError", | |||
|
51 | "logDebug", | |||
|
52 | "logFatal", | |||
|
53 | "logWarning" | |||
|
54 | ]; | |||
|
55 | ||||
|
56 | ||||
|
57 | MochiKit.Logging.EXPORT_OK = [ | |||
|
58 | "logLevelAtLeast", | |||
|
59 | "isLogMessage", | |||
|
60 | "compareLogMessage" | |||
|
61 | ]; | |||
|
62 | ||||
|
63 | ||||
|
64 | /** @id MochiKit.Logging.LogMessage */ | |||
|
65 | MochiKit.Logging.LogMessage = function (num, level, info) { | |||
|
66 | this.num = num; | |||
|
67 | this.level = level; | |||
|
68 | this.info = info; | |||
|
69 | this.timestamp = new Date(); | |||
|
70 | }; | |||
|
71 | ||||
|
72 | MochiKit.Logging.LogMessage.prototype = { | |||
|
73 | /** @id MochiKit.Logging.LogMessage.prototype.repr */ | |||
|
74 | repr: function () { | |||
|
75 | var m = MochiKit.Base; | |||
|
76 | return 'LogMessage(' + | |||
|
77 | m.map( | |||
|
78 | m.repr, | |||
|
79 | [this.num, this.level, this.info] | |||
|
80 | ).join(', ') + ')'; | |||
|
81 | }, | |||
|
82 | /** @id MochiKit.Logging.LogMessage.prototype.toString */ | |||
|
83 | toString: MochiKit.Base.forwardCall("repr") | |||
|
84 | }; | |||
|
85 | ||||
|
86 | MochiKit.Base.update(MochiKit.Logging, { | |||
|
87 | /** @id MochiKit.Logging.logLevelAtLeast */ | |||
|
88 | logLevelAtLeast: function (minLevel) { | |||
|
89 | var self = MochiKit.Logging; | |||
|
90 | if (typeof(minLevel) == 'string') { | |||
|
91 | minLevel = self.LogLevel[minLevel]; | |||
|
92 | } | |||
|
93 | return function (msg) { | |||
|
94 | var msgLevel = msg.level; | |||
|
95 | if (typeof(msgLevel) == 'string') { | |||
|
96 | msgLevel = self.LogLevel[msgLevel]; | |||
|
97 | } | |||
|
98 | return msgLevel >= minLevel; | |||
|
99 | }; | |||
|
100 | }, | |||
|
101 | ||||
|
102 | /** @id MochiKit.Logging.isLogMessage */ | |||
|
103 | isLogMessage: function (/* ... */) { | |||
|
104 | var LogMessage = MochiKit.Logging.LogMessage; | |||
|
105 | for (var i = 0; i < arguments.length; i++) { | |||
|
106 | if (!(arguments[i] instanceof LogMessage)) { | |||
|
107 | return false; | |||
|
108 | } | |||
|
109 | } | |||
|
110 | return true; | |||
|
111 | }, | |||
|
112 | ||||
|
113 | /** @id MochiKit.Logging.compareLogMessage */ | |||
|
114 | compareLogMessage: function (a, b) { | |||
|
115 | return MochiKit.Base.compare([a.level, a.info], [b.level, b.info]); | |||
|
116 | }, | |||
|
117 | ||||
|
118 | /** @id MochiKit.Logging.alertListener */ | |||
|
119 | alertListener: function (msg) { | |||
|
120 | alert( | |||
|
121 | "num: " + msg.num + | |||
|
122 | "\nlevel: " + msg.level + | |||
|
123 | "\ninfo: " + msg.info.join(" ") | |||
|
124 | ); | |||
|
125 | } | |||
|
126 | ||||
|
127 | }); | |||
|
128 | ||||
|
129 | /** @id MochiKit.Logging.Logger */ | |||
|
130 | MochiKit.Logging.Logger = function (/* optional */maxSize) { | |||
|
131 | this.counter = 0; | |||
|
132 | if (typeof(maxSize) == 'undefined' || maxSize === null) { | |||
|
133 | maxSize = -1; | |||
|
134 | } | |||
|
135 | this.maxSize = maxSize; | |||
|
136 | this._messages = []; | |||
|
137 | this.listeners = {}; | |||
|
138 | this.useNativeConsole = false; | |||
|
139 | }; | |||
|
140 | ||||
|
141 | MochiKit.Logging.Logger.prototype = { | |||
|
142 | /** @id MochiKit.Logging.Logger.prototype.clear */ | |||
|
143 | clear: function () { | |||
|
144 | this._messages.splice(0, this._messages.length); | |||
|
145 | }, | |||
|
146 | ||||
|
147 | /** @id MochiKit.Logging.Logger.prototype.logToConsole */ | |||
|
148 | logToConsole: function (msg) { | |||
|
149 | if (typeof(window) != "undefined" && window.console | |||
|
150 | && window.console.log) { | |||
|
151 | // Safari and FireBug 0.4 | |||
|
152 | // Percent replacement is a workaround for cute Safari crashing bug | |||
|
153 | window.console.log(msg.replace(/%/g, '\uFF05')); | |||
|
154 | } else if (typeof(opera) != "undefined" && opera.postError) { | |||
|
155 | // Opera | |||
|
156 | opera.postError(msg); | |||
|
157 | } else if (typeof(printfire) == "function") { | |||
|
158 | // FireBug 0.3 and earlier | |||
|
159 | printfire(msg); | |||
|
160 | } else if (typeof(Debug) != "undefined" && Debug.writeln) { | |||
|
161 | // IE Web Development Helper (?) | |||
|
162 | // http://www.nikhilk.net/Entry.aspx?id=93 | |||
|
163 | Debug.writeln(msg); | |||
|
164 | } else if (typeof(debug) != "undefined" && debug.trace) { | |||
|
165 | // Atlas framework (?) | |||
|
166 | // http://www.nikhilk.net/Entry.aspx?id=93 | |||
|
167 | debug.trace(msg); | |||
|
168 | } | |||
|
169 | }, | |||
|
170 | ||||
|
171 | /** @id MochiKit.Logging.Logger.prototype.dispatchListeners */ | |||
|
172 | dispatchListeners: function (msg) { | |||
|
173 | for (var k in this.listeners) { | |||
|
174 | var pair = this.listeners[k]; | |||
|
175 | if (pair.ident != k || (pair[0] && !pair[0](msg))) { | |||
|
176 | continue; | |||
|
177 | } | |||
|
178 | pair[1](msg); | |||
|
179 | } | |||
|
180 | }, | |||
|
181 | ||||
|
182 | /** @id MochiKit.Logging.Logger.prototype.addListener */ | |||
|
183 | addListener: function (ident, filter, listener) { | |||
|
184 | if (typeof(filter) == 'string') { | |||
|
185 | filter = MochiKit.Logging.logLevelAtLeast(filter); | |||
|
186 | } | |||
|
187 | var entry = [filter, listener]; | |||
|
188 | entry.ident = ident; | |||
|
189 | this.listeners[ident] = entry; | |||
|
190 | }, | |||
|
191 | ||||
|
192 | /** @id MochiKit.Logging.Logger.prototype.removeListener */ | |||
|
193 | removeListener: function (ident) { | |||
|
194 | delete this.listeners[ident]; | |||
|
195 | }, | |||
|
196 | ||||
|
197 | /** @id MochiKit.Logging.Logger.prototype.baseLog */ | |||
|
198 | baseLog: function (level, message/*, ...*/) { | |||
|
199 | var msg = new MochiKit.Logging.LogMessage( | |||
|
200 | this.counter, | |||
|
201 | level, | |||
|
202 | MochiKit.Base.extend(null, arguments, 1) | |||
|
203 | ); | |||
|
204 | this._messages.push(msg); | |||
|
205 | this.dispatchListeners(msg); | |||
|
206 | if (this.useNativeConsole) { | |||
|
207 | this.logToConsole(msg.level + ": " + msg.info.join(" ")); | |||
|
208 | } | |||
|
209 | this.counter += 1; | |||
|
210 | while (this.maxSize >= 0 && this._messages.length > this.maxSize) { | |||
|
211 | this._messages.shift(); | |||
|
212 | } | |||
|
213 | }, | |||
|
214 | ||||
|
215 | /** @id MochiKit.Logging.Logger.prototype.getMessages */ | |||
|
216 | getMessages: function (howMany) { | |||
|
217 | var firstMsg = 0; | |||
|
218 | if (!(typeof(howMany) == 'undefined' || howMany === null)) { | |||
|
219 | firstMsg = Math.max(0, this._messages.length - howMany); | |||
|
220 | } | |||
|
221 | return this._messages.slice(firstMsg); | |||
|
222 | }, | |||
|
223 | ||||
|
224 | /** @id MochiKit.Logging.Logger.prototype.getMessageText */ | |||
|
225 | getMessageText: function (howMany) { | |||
|
226 | if (typeof(howMany) == 'undefined' || howMany === null) { | |||
|
227 | howMany = 30; | |||
|
228 | } | |||
|
229 | var messages = this.getMessages(howMany); | |||
|
230 | if (messages.length) { | |||
|
231 | var lst = map(function (m) { | |||
|
232 | return '\n [' + m.num + '] ' + m.level + ': ' + m.info.join(' '); | |||
|
233 | }, messages); | |||
|
234 | lst.unshift('LAST ' + messages.length + ' MESSAGES:'); | |||
|
235 | return lst.join(''); | |||
|
236 | } | |||
|
237 | return ''; | |||
|
238 | }, | |||
|
239 | ||||
|
240 | /** @id MochiKit.Logging.Logger.prototype.debuggingBookmarklet */ | |||
|
241 | debuggingBookmarklet: function (inline) { | |||
|
242 | if (typeof(MochiKit.LoggingPane) == "undefined") { | |||
|
243 | alert(this.getMessageText()); | |||
|
244 | } else { | |||
|
245 | MochiKit.LoggingPane.createLoggingPane(inline || false); | |||
|
246 | } | |||
|
247 | } | |||
|
248 | }; | |||
|
249 | ||||
|
250 | MochiKit.Logging.__new__ = function () { | |||
|
251 | this.LogLevel = { | |||
|
252 | ERROR: 40, | |||
|
253 | FATAL: 50, | |||
|
254 | WARNING: 30, | |||
|
255 | INFO: 20, | |||
|
256 | DEBUG: 10 | |||
|
257 | }; | |||
|
258 | ||||
|
259 | var m = MochiKit.Base; | |||
|
260 | m.registerComparator("LogMessage", | |||
|
261 | this.isLogMessage, | |||
|
262 | this.compareLogMessage | |||
|
263 | ); | |||
|
264 | ||||
|
265 | var partial = m.partial; | |||
|
266 | ||||
|
267 | var Logger = this.Logger; | |||
|
268 | var baseLog = Logger.prototype.baseLog; | |||
|
269 | m.update(this.Logger.prototype, { | |||
|
270 | debug: partial(baseLog, 'DEBUG'), | |||
|
271 | log: partial(baseLog, 'INFO'), | |||
|
272 | error: partial(baseLog, 'ERROR'), | |||
|
273 | fatal: partial(baseLog, 'FATAL'), | |||
|
274 | warning: partial(baseLog, 'WARNING') | |||
|
275 | }); | |||
|
276 | ||||
|
277 | // indirectly find logger so it can be replaced | |||
|
278 | var self = this; | |||
|
279 | var connectLog = function (name) { | |||
|
280 | return function () { | |||
|
281 | self.logger[name].apply(self.logger, arguments); | |||
|
282 | }; | |||
|
283 | }; | |||
|
284 | ||||
|
285 | /** @id MochiKit.Logging.log */ | |||
|
286 | this.log = connectLog('log'); | |||
|
287 | /** @id MochiKit.Logging.logError */ | |||
|
288 | this.logError = connectLog('error'); | |||
|
289 | /** @id MochiKit.Logging.logDebug */ | |||
|
290 | this.logDebug = connectLog('debug'); | |||
|
291 | /** @id MochiKit.Logging.logFatal */ | |||
|
292 | this.logFatal = connectLog('fatal'); | |||
|
293 | /** @id MochiKit.Logging.logWarning */ | |||
|
294 | this.logWarning = connectLog('warning'); | |||
|
295 | this.logger = new Logger(); | |||
|
296 | this.logger.useNativeConsole = true; | |||
|
297 | ||||
|
298 | this.EXPORT_TAGS = { | |||
|
299 | ":common": this.EXPORT, | |||
|
300 | ":all": m.concat(this.EXPORT, this.EXPORT_OK) | |||
|
301 | }; | |||
|
302 | ||||
|
303 | m.nameFunctions(this); | |||
|
304 | ||||
|
305 | }; | |||
|
306 | ||||
|
307 | if (typeof(printfire) == "undefined" && | |||
|
308 | typeof(document) != "undefined" && document.createEvent && | |||
|
309 | typeof(dispatchEvent) != "undefined") { | |||
|
310 | // FireBug really should be less lame about this global function | |||
|
311 | printfire = function () { | |||
|
312 | printfire.args = arguments; | |||
|
313 | var ev = document.createEvent("Events"); | |||
|
314 | ev.initEvent("printfire", false, true); | |||
|
315 | dispatchEvent(ev); | |||
|
316 | }; | |||
|
317 | } | |||
|
318 | ||||
|
319 | MochiKit.Logging.__new__(); | |||
|
320 | ||||
|
321 | MochiKit.Base._exportSymbols(this, MochiKit.Logging); |
@@ -0,0 +1,374 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.LoggingPane 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.LoggingPane'); | |||
|
13 | dojo.require('MochiKit.Logging'); | |||
|
14 | dojo.require('MochiKit.Base'); | |||
|
15 | } | |||
|
16 | ||||
|
17 | if (typeof(JSAN) != 'undefined') { | |||
|
18 | JSAN.use("MochiKit.Logging", []); | |||
|
19 | JSAN.use("MochiKit.Base", []); | |||
|
20 | } | |||
|
21 | ||||
|
22 | try { | |||
|
23 | if (typeof(MochiKit.Base) == 'undefined' || typeof(MochiKit.Logging) == 'undefined') { | |||
|
24 | throw ""; | |||
|
25 | } | |||
|
26 | } catch (e) { | |||
|
27 | throw "MochiKit.LoggingPane depends on MochiKit.Base and MochiKit.Logging!"; | |||
|
28 | } | |||
|
29 | ||||
|
30 | if (typeof(MochiKit.LoggingPane) == 'undefined') { | |||
|
31 | MochiKit.LoggingPane = {}; | |||
|
32 | } | |||
|
33 | ||||
|
34 | MochiKit.LoggingPane.NAME = "MochiKit.LoggingPane"; | |||
|
35 | MochiKit.LoggingPane.VERSION = "1.4"; | |||
|
36 | MochiKit.LoggingPane.__repr__ = function () { | |||
|
37 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
38 | }; | |||
|
39 | ||||
|
40 | MochiKit.LoggingPane.toString = function () { | |||
|
41 | return this.__repr__(); | |||
|
42 | }; | |||
|
43 | ||||
|
44 | /** @id MochiKit.LoggingPane.createLoggingPane */ | |||
|
45 | MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) { | |||
|
46 | var m = MochiKit.LoggingPane; | |||
|
47 | inline = !(!inline); | |||
|
48 | if (m._loggingPane && m._loggingPane.inline != inline) { | |||
|
49 | m._loggingPane.closePane(); | |||
|
50 | m._loggingPane = null; | |||
|
51 | } | |||
|
52 | if (!m._loggingPane || m._loggingPane.closed) { | |||
|
53 | m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger); | |||
|
54 | } | |||
|
55 | return m._loggingPane; | |||
|
56 | }; | |||
|
57 | ||||
|
58 | /** @id MochiKit.LoggingPane.LoggingPane */ | |||
|
59 | MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) { | |||
|
60 | ||||
|
61 | /* Use a div if inline, pop up a window if not */ | |||
|
62 | /* Create the elements */ | |||
|
63 | if (typeof(logger) == "undefined" || logger === null) { | |||
|
64 | logger = MochiKit.Logging.logger; | |||
|
65 | } | |||
|
66 | this.logger = logger; | |||
|
67 | var update = MochiKit.Base.update; | |||
|
68 | var updatetree = MochiKit.Base.updatetree; | |||
|
69 | var bind = MochiKit.Base.bind; | |||
|
70 | var clone = MochiKit.Base.clone; | |||
|
71 | var win = window; | |||
|
72 | var uid = "_MochiKit_LoggingPane"; | |||
|
73 | if (typeof(MochiKit.DOM) != "undefined") { | |||
|
74 | win = MochiKit.DOM.currentWindow(); | |||
|
75 | } | |||
|
76 | if (!inline) { | |||
|
77 | // name the popup with the base URL for uniqueness | |||
|
78 | var url = win.location.href.split("?")[0].replace(/[#:\/.><&-]/g, "_"); | |||
|
79 | var name = uid + "_" + url; | |||
|
80 | var nwin = win.open("", name, "dependent,resizable,height=200"); | |||
|
81 | if (!nwin) { | |||
|
82 | alert("Not able to open debugging window due to pop-up blocking."); | |||
|
83 | return undefined; | |||
|
84 | } | |||
|
85 | nwin.document.write( | |||
|
86 | '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" ' | |||
|
87 | + '"http://www.w3.org/TR/html4/loose.dtd">' | |||
|
88 | + '<html><head><title>[MochiKit.LoggingPane]</title></head>' | |||
|
89 | + '<body></body></html>' | |||
|
90 | ); | |||
|
91 | nwin.document.close(); | |||
|
92 | nwin.document.title += ' ' + win.document.title; | |||
|
93 | win = nwin; | |||
|
94 | } | |||
|
95 | var doc = win.document; | |||
|
96 | this.doc = doc; | |||
|
97 | ||||
|
98 | // Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed) | |||
|
99 | var debugPane = doc.getElementById(uid); | |||
|
100 | var existing_pane = !!debugPane; | |||
|
101 | if (debugPane && typeof(debugPane.loggingPane) != "undefined") { | |||
|
102 | debugPane.loggingPane.logger = this.logger; | |||
|
103 | debugPane.loggingPane.buildAndApplyFilter(); | |||
|
104 | return debugPane.loggingPane; | |||
|
105 | } | |||
|
106 | ||||
|
107 | if (existing_pane) { | |||
|
108 | // clear any existing contents | |||
|
109 | var child; | |||
|
110 | while ((child = debugPane.firstChild)) { | |||
|
111 | debugPane.removeChild(child); | |||
|
112 | } | |||
|
113 | } else { | |||
|
114 | debugPane = doc.createElement("div"); | |||
|
115 | debugPane.id = uid; | |||
|
116 | } | |||
|
117 | debugPane.loggingPane = this; | |||
|
118 | var levelFilterField = doc.createElement("input"); | |||
|
119 | var infoFilterField = doc.createElement("input"); | |||
|
120 | var filterButton = doc.createElement("button"); | |||
|
121 | var loadButton = doc.createElement("button"); | |||
|
122 | var clearButton = doc.createElement("button"); | |||
|
123 | var closeButton = doc.createElement("button"); | |||
|
124 | var logPaneArea = doc.createElement("div"); | |||
|
125 | var logPane = doc.createElement("div"); | |||
|
126 | ||||
|
127 | /* Set up the functions */ | |||
|
128 | var listenerId = uid + "_Listener"; | |||
|
129 | this.colorTable = clone(this.colorTable); | |||
|
130 | var messages = []; | |||
|
131 | var messageFilter = null; | |||
|
132 | ||||
|
133 | /** @id MochiKit.LoggingPane.messageLevel */ | |||
|
134 | var messageLevel = function (msg) { | |||
|
135 | var level = msg.level; | |||
|
136 | if (typeof(level) == "number") { | |||
|
137 | level = MochiKit.Logging.LogLevel[level]; | |||
|
138 | } | |||
|
139 | return level; | |||
|
140 | }; | |||
|
141 | ||||
|
142 | /** @id MochiKit.LoggingPane.messageText */ | |||
|
143 | var messageText = function (msg) { | |||
|
144 | return msg.info.join(" "); | |||
|
145 | }; | |||
|
146 | ||||
|
147 | /** @id MochiKit.LoggingPane.addMessageText */ | |||
|
148 | var addMessageText = bind(function (msg) { | |||
|
149 | var level = messageLevel(msg); | |||
|
150 | var text = messageText(msg); | |||
|
151 | var c = this.colorTable[level]; | |||
|
152 | var p = doc.createElement("span"); | |||
|
153 | p.className = "MochiKit-LogMessage MochiKit-LogLevel-" + level; | |||
|
154 | p.style.cssText = "margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: " + c; | |||
|
155 | p.appendChild(doc.createTextNode(level + ": " + text)); | |||
|
156 | logPane.appendChild(p); | |||
|
157 | logPane.appendChild(doc.createElement("br")); | |||
|
158 | if (logPaneArea.offsetHeight > logPaneArea.scrollHeight) { | |||
|
159 | logPaneArea.scrollTop = 0; | |||
|
160 | } else { | |||
|
161 | logPaneArea.scrollTop = logPaneArea.scrollHeight; | |||
|
162 | } | |||
|
163 | }, this); | |||
|
164 | ||||
|
165 | /** @id MochiKit.LoggingPane.addMessage */ | |||
|
166 | var addMessage = function (msg) { | |||
|
167 | messages[messages.length] = msg; | |||
|
168 | addMessageText(msg); | |||
|
169 | }; | |||
|
170 | ||||
|
171 | /** @id MochiKit.LoggingPane.buildMessageFilter */ | |||
|
172 | var buildMessageFilter = function () { | |||
|
173 | var levelre, infore; | |||
|
174 | try { | |||
|
175 | /* Catch any exceptions that might arise due to invalid regexes */ | |||
|
176 | levelre = new RegExp(levelFilterField.value); | |||
|
177 | infore = new RegExp(infoFilterField.value); | |||
|
178 | } catch(e) { | |||
|
179 | /* If there was an error with the regexes, do no filtering */ | |||
|
180 | logDebug("Error in filter regex: " + e.message); | |||
|
181 | return null; | |||
|
182 | } | |||
|
183 | ||||
|
184 | return function (msg) { | |||
|
185 | return ( | |||
|
186 | levelre.test(messageLevel(msg)) && | |||
|
187 | infore.test(messageText(msg)) | |||
|
188 | ); | |||
|
189 | }; | |||
|
190 | }; | |||
|
191 | ||||
|
192 | /** @id MochiKit.LoggingPane.clearMessagePane */ | |||
|
193 | var clearMessagePane = function () { | |||
|
194 | while (logPane.firstChild) { | |||
|
195 | logPane.removeChild(logPane.firstChild); | |||
|
196 | } | |||
|
197 | }; | |||
|
198 | ||||
|
199 | /** @id MochiKit.LoggingPane.clearMessages */ | |||
|
200 | var clearMessages = function () { | |||
|
201 | messages = []; | |||
|
202 | clearMessagePane(); | |||
|
203 | }; | |||
|
204 | ||||
|
205 | /** @id MochiKit.LoggingPane.closePane */ | |||
|
206 | var closePane = bind(function () { | |||
|
207 | if (this.closed) { | |||
|
208 | return; | |||
|
209 | } | |||
|
210 | this.closed = true; | |||
|
211 | if (MochiKit.LoggingPane._loggingPane == this) { | |||
|
212 | MochiKit.LoggingPane._loggingPane = null; | |||
|
213 | } | |||
|
214 | this.logger.removeListener(listenerId); | |||
|
215 | try { | |||
|
216 | try { | |||
|
217 | debugPane.loggingPane = null; | |||
|
218 | } catch(e) { logFatal("Bookmarklet was closed incorrectly."); } | |||
|
219 | if (inline) { | |||
|
220 | debugPane.parentNode.removeChild(debugPane); | |||
|
221 | } else { | |||
|
222 | this.win.close(); | |||
|
223 | } | |||
|
224 | } catch(e) {} | |||
|
225 | }, this); | |||
|
226 | ||||
|
227 | /** @id MochiKit.LoggingPane.filterMessages */ | |||
|
228 | var filterMessages = function () { | |||
|
229 | clearMessagePane(); | |||
|
230 | ||||
|
231 | for (var i = 0; i < messages.length; i++) { | |||
|
232 | var msg = messages[i]; | |||
|
233 | if (messageFilter === null || messageFilter(msg)) { | |||
|
234 | addMessageText(msg); | |||
|
235 | } | |||
|
236 | } | |||
|
237 | }; | |||
|
238 | ||||
|
239 | this.buildAndApplyFilter = function () { | |||
|
240 | messageFilter = buildMessageFilter(); | |||
|
241 | ||||
|
242 | filterMessages(); | |||
|
243 | ||||
|
244 | this.logger.removeListener(listenerId); | |||
|
245 | this.logger.addListener(listenerId, messageFilter, addMessage); | |||
|
246 | }; | |||
|
247 | ||||
|
248 | ||||
|
249 | /** @id MochiKit.LoggingPane.loadMessages */ | |||
|
250 | var loadMessages = bind(function () { | |||
|
251 | messages = this.logger.getMessages(); | |||
|
252 | filterMessages(); | |||
|
253 | }, this); | |||
|
254 | ||||
|
255 | /** @id MochiKit.LoggingPane.filterOnEnter */ | |||
|
256 | var filterOnEnter = bind(function (event) { | |||
|
257 | event = event || window.event; | |||
|
258 | key = event.which || event.keyCode; | |||
|
259 | if (key == 13) { | |||
|
260 | this.buildAndApplyFilter(); | |||
|
261 | } | |||
|
262 | }, this); | |||
|
263 | ||||
|
264 | /* Create the debug pane */ | |||
|
265 | var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont; | |||
|
266 | if (inline) { | |||
|
267 | style += "; height: 10em; border-top: 2px solid black"; | |||
|
268 | } else { | |||
|
269 | style += "; height: 100%;"; | |||
|
270 | } | |||
|
271 | debugPane.style.cssText = style; | |||
|
272 | ||||
|
273 | if (!existing_pane) { | |||
|
274 | doc.body.appendChild(debugPane); | |||
|
275 | } | |||
|
276 | ||||
|
277 | /* Create the filter fields */ | |||
|
278 | style = {"cssText": "width: 33%; display: inline; font: " + this.logFont}; | |||
|
279 | ||||
|
280 | updatetree(levelFilterField, { | |||
|
281 | "value": "FATAL|ERROR|WARNING|INFO|DEBUG", | |||
|
282 | "onkeypress": filterOnEnter, | |||
|
283 | "style": style | |||
|
284 | }); | |||
|
285 | debugPane.appendChild(levelFilterField); | |||
|
286 | ||||
|
287 | updatetree(infoFilterField, { | |||
|
288 | "value": ".*", | |||
|
289 | "onkeypress": filterOnEnter, | |||
|
290 | "style": style | |||
|
291 | }); | |||
|
292 | debugPane.appendChild(infoFilterField); | |||
|
293 | ||||
|
294 | /* Create the buttons */ | |||
|
295 | style = "width: 8%; display:inline; font: " + this.logFont; | |||
|
296 | ||||
|
297 | filterButton.appendChild(doc.createTextNode("Filter")); | |||
|
298 | filterButton.onclick = bind("buildAndApplyFilter", this); | |||
|
299 | filterButton.style.cssText = style; | |||
|
300 | debugPane.appendChild(filterButton); | |||
|
301 | ||||
|
302 | loadButton.appendChild(doc.createTextNode("Load")); | |||
|
303 | loadButton.onclick = loadMessages; | |||
|
304 | loadButton.style.cssText = style; | |||
|
305 | debugPane.appendChild(loadButton); | |||
|
306 | ||||
|
307 | clearButton.appendChild(doc.createTextNode("Clear")); | |||
|
308 | clearButton.onclick = clearMessages; | |||
|
309 | clearButton.style.cssText = style; | |||
|
310 | debugPane.appendChild(clearButton); | |||
|
311 | ||||
|
312 | closeButton.appendChild(doc.createTextNode("Close")); | |||
|
313 | closeButton.onclick = closePane; | |||
|
314 | closeButton.style.cssText = style; | |||
|
315 | debugPane.appendChild(closeButton); | |||
|
316 | ||||
|
317 | /* Create the logging pane */ | |||
|
318 | logPaneArea.style.cssText = "overflow: auto; width: 100%"; | |||
|
319 | logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%"); | |||
|
320 | ||||
|
321 | logPaneArea.appendChild(logPane); | |||
|
322 | debugPane.appendChild(logPaneArea); | |||
|
323 | ||||
|
324 | this.buildAndApplyFilter(); | |||
|
325 | loadMessages(); | |||
|
326 | ||||
|
327 | if (inline) { | |||
|
328 | this.win = undefined; | |||
|
329 | } else { | |||
|
330 | this.win = win; | |||
|
331 | } | |||
|
332 | this.inline = inline; | |||
|
333 | this.closePane = closePane; | |||
|
334 | this.closed = false; | |||
|
335 | ||||
|
336 | ||||
|
337 | return this; | |||
|
338 | }; | |||
|
339 | ||||
|
340 | MochiKit.LoggingPane.LoggingPane.prototype = { | |||
|
341 | "logFont": "8pt Verdana,sans-serif", | |||
|
342 | "colorTable": { | |||
|
343 | "ERROR": "red", | |||
|
344 | "FATAL": "darkred", | |||
|
345 | "WARNING": "blue", | |||
|
346 | "INFO": "black", | |||
|
347 | "DEBUG": "green" | |||
|
348 | } | |||
|
349 | }; | |||
|
350 | ||||
|
351 | ||||
|
352 | MochiKit.LoggingPane.EXPORT_OK = [ | |||
|
353 | "LoggingPane" | |||
|
354 | ]; | |||
|
355 | ||||
|
356 | MochiKit.LoggingPane.EXPORT = [ | |||
|
357 | "createLoggingPane" | |||
|
358 | ]; | |||
|
359 | ||||
|
360 | MochiKit.LoggingPane.__new__ = function () { | |||
|
361 | this.EXPORT_TAGS = { | |||
|
362 | ":common": this.EXPORT, | |||
|
363 | ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK) | |||
|
364 | }; | |||
|
365 | ||||
|
366 | MochiKit.Base.nameFunctions(this); | |||
|
367 | ||||
|
368 | MochiKit.LoggingPane._loggingPane = null; | |||
|
369 | ||||
|
370 | }; | |||
|
371 | ||||
|
372 | MochiKit.LoggingPane.__new__(); | |||
|
373 | ||||
|
374 | MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane); |
@@ -0,0 +1,154 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.MochiKit 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(MochiKit) == 'undefined') { | |||
|
12 | MochiKit = {}; | |||
|
13 | } | |||
|
14 | ||||
|
15 | if (typeof(MochiKit.MochiKit) == 'undefined') { | |||
|
16 | /** @id MochiKit.MochiKit */ | |||
|
17 | MochiKit.MochiKit = {}; | |||
|
18 | } | |||
|
19 | ||||
|
20 | MochiKit.MochiKit.NAME = "MochiKit.MochiKit"; | |||
|
21 | MochiKit.MochiKit.VERSION = "1.4"; | |||
|
22 | MochiKit.MochiKit.__repr__ = function () { | |||
|
23 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
24 | }; | |||
|
25 | ||||
|
26 | /** @id MochiKit.MochiKit.toString */ | |||
|
27 | MochiKit.MochiKit.toString = function () { | |||
|
28 | return this.__repr__(); | |||
|
29 | }; | |||
|
30 | ||||
|
31 | /** @id MochiKit.MochiKit.SUBMODULES */ | |||
|
32 | MochiKit.MochiKit.SUBMODULES = [ | |||
|
33 | "Base", | |||
|
34 | "Iter", | |||
|
35 | "Logging", | |||
|
36 | "DateTime", | |||
|
37 | "Format", | |||
|
38 | "Async", | |||
|
39 | "DOM", | |||
|
40 | "Selector", | |||
|
41 | "Style", | |||
|
42 | "LoggingPane", | |||
|
43 | "Color", | |||
|
44 | "Signal", | |||
|
45 | "Position", | |||
|
46 | "Visual" | |||
|
47 | ]; | |||
|
48 | ||||
|
49 | if (typeof(JSAN) != 'undefined' || typeof(dojo) != 'undefined') { | |||
|
50 | if (typeof(dojo) != 'undefined') { | |||
|
51 | dojo.provide('MochiKit.MochiKit'); | |||
|
52 | dojo.require("MochiKit.*"); | |||
|
53 | } | |||
|
54 | if (typeof(JSAN) != 'undefined') { | |||
|
55 | (function (lst) { | |||
|
56 | for (var i = 0; i < lst.length; i++) { | |||
|
57 | JSAN.use("MochiKit." + lst[i], []); | |||
|
58 | } | |||
|
59 | })(MochiKit.MochiKit.SUBMODULES); | |||
|
60 | } | |||
|
61 | (function () { | |||
|
62 | var extend = MochiKit.Base.extend; | |||
|
63 | var self = MochiKit.MochiKit; | |||
|
64 | var modules = self.SUBMODULES; | |||
|
65 | var EXPORT = []; | |||
|
66 | var EXPORT_OK = []; | |||
|
67 | var EXPORT_TAGS = {}; | |||
|
68 | var i, k, m, all; | |||
|
69 | for (i = 0; i < modules.length; i++) { | |||
|
70 | m = MochiKit[modules[i]]; | |||
|
71 | extend(EXPORT, m.EXPORT); | |||
|
72 | extend(EXPORT_OK, m.EXPORT_OK); | |||
|
73 | for (k in m.EXPORT_TAGS) { | |||
|
74 | EXPORT_TAGS[k] = extend(EXPORT_TAGS[k], m.EXPORT_TAGS[k]); | |||
|
75 | } | |||
|
76 | all = m.EXPORT_TAGS[":all"]; | |||
|
77 | if (!all) { | |||
|
78 | all = extend(null, m.EXPORT, m.EXPORT_OK); | |||
|
79 | } | |||
|
80 | var j; | |||
|
81 | for (j = 0; j < all.length; j++) { | |||
|
82 | k = all[j]; | |||
|
83 | self[k] = m[k]; | |||
|
84 | } | |||
|
85 | } | |||
|
86 | self.EXPORT = EXPORT; | |||
|
87 | self.EXPORT_OK = EXPORT_OK; | |||
|
88 | self.EXPORT_TAGS = EXPORT_TAGS; | |||
|
89 | }()); | |||
|
90 | ||||
|
91 | } else { | |||
|
92 | if (typeof(MochiKit.__compat__) == 'undefined') { | |||
|
93 | MochiKit.__compat__ = true; | |||
|
94 | } | |||
|
95 | (function () { | |||
|
96 | if (typeof(document) == "undefined") { | |||
|
97 | return; | |||
|
98 | } | |||
|
99 | var scripts = document.getElementsByTagName("script"); | |||
|
100 | var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; | |||
|
101 | var base = null; | |||
|
102 | var baseElem = null; | |||
|
103 | var allScripts = {}; | |||
|
104 | var i; | |||
|
105 | for (i = 0; i < scripts.length; i++) { | |||
|
106 | var src = scripts[i].getAttribute("src"); | |||
|
107 | if (!src) { | |||
|
108 | continue; | |||
|
109 | } | |||
|
110 | allScripts[src] = true; | |||
|
111 | if (src.match(/MochiKit.js$/)) { | |||
|
112 | base = src.substring(0, src.lastIndexOf('MochiKit.js')); | |||
|
113 | baseElem = scripts[i]; | |||
|
114 | } | |||
|
115 | } | |||
|
116 | if (base === null) { | |||
|
117 | return; | |||
|
118 | } | |||
|
119 | var modules = MochiKit.MochiKit.SUBMODULES; | |||
|
120 | for (var i = 0; i < modules.length; i++) { | |||
|
121 | if (MochiKit[modules[i]]) { | |||
|
122 | continue; | |||
|
123 | } | |||
|
124 | var uri = base + modules[i] + '.js'; | |||
|
125 | if (uri in allScripts) { | |||
|
126 | continue; | |||
|
127 | } | |||
|
128 | if (document.documentElement && | |||
|
129 | document.documentElement.namespaceURI == kXULNSURI) { | |||
|
130 | // XUL | |||
|
131 | var s = document.createElementNS(kXULNSURI, 'script'); | |||
|
132 | s.setAttribute("id", "MochiKit_" + base + modules[i]); | |||
|
133 | s.setAttribute("src", uri); | |||
|
134 | s.setAttribute("type", "application/x-javascript"); | |||
|
135 | baseElem.parentNode.appendChild(s); | |||
|
136 | } else { | |||
|
137 | // HTML | |||
|
138 | /* | |||
|
139 | DOM can not be used here because Safari does | |||
|
140 | deferred loading of scripts unless they are | |||
|
141 | in the document or inserted with document.write | |||
|
142 | ||||
|
143 | This is not XHTML compliant. If you want XHTML | |||
|
144 | compliance then you must use the packed version of MochiKit | |||
|
145 | or include each script individually (basically unroll | |||
|
146 | these document.write calls into your XHTML source) | |||
|
147 | ||||
|
148 | */ | |||
|
149 | document.write('<script src="' + uri + | |||
|
150 | '" type="text/javascript"></script>'); | |||
|
151 | } | |||
|
152 | }; | |||
|
153 | })(); | |||
|
154 | } |
@@ -0,0 +1,115 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.MockDOM 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(MochiKit) == "undefined") { | |||
|
12 | MochiKit = {}; | |||
|
13 | } | |||
|
14 | ||||
|
15 | if (typeof(MochiKit.MockDOM) == "undefined") { | |||
|
16 | MochiKit.MockDOM = {}; | |||
|
17 | } | |||
|
18 | ||||
|
19 | MochiKit.MockDOM.NAME = "MochiKit.MockDOM"; | |||
|
20 | MochiKit.MockDOM.VERSION = "1.4"; | |||
|
21 | ||||
|
22 | MochiKit.MockDOM.__repr__ = function () { | |||
|
23 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
24 | }; | |||
|
25 | ||||
|
26 | /** @id MochiKit.MockDOM.toString */ | |||
|
27 | MochiKit.MockDOM.toString = function () { | |||
|
28 | return this.__repr__(); | |||
|
29 | }; | |||
|
30 | ||||
|
31 | /** @id MochiKit.MockDOM.createDocument */ | |||
|
32 | MochiKit.MockDOM.createDocument = function () { | |||
|
33 | var doc = new MochiKit.MockDOM.MockElement("DOCUMENT"); | |||
|
34 | doc.body = doc.createElement("BODY"); | |||
|
35 | doc.appendChild(doc.body); | |||
|
36 | return doc; | |||
|
37 | }; | |||
|
38 | ||||
|
39 | /** @id MochiKit.MockDOM.MockElement */ | |||
|
40 | MochiKit.MockDOM.MockElement = function (name, data, ownerDocument) { | |||
|
41 | this.tagName = this.nodeName = name.toUpperCase(); | |||
|
42 | this.ownerDocument = ownerDocument || null; | |||
|
43 | if (name == "DOCUMENT") { | |||
|
44 | this.nodeType = 9; | |||
|
45 | this.childNodes = []; | |||
|
46 | } else if (typeof(data) == "string") { | |||
|
47 | this.nodeValue = data; | |||
|
48 | this.nodeType = 3; | |||
|
49 | } else { | |||
|
50 | this.nodeType = 1; | |||
|
51 | this.childNodes = []; | |||
|
52 | } | |||
|
53 | if (name.substring(0, 1) == "<") { | |||
|
54 | var nameattr = name.substring( | |||
|
55 | name.indexOf('"') + 1, name.lastIndexOf('"')); | |||
|
56 | name = name.substring(1, name.indexOf(" ")); | |||
|
57 | this.tagName = this.nodeName = name.toUpperCase(); | |||
|
58 | this.setAttribute("name", nameattr); | |||
|
59 | } | |||
|
60 | }; | |||
|
61 | ||||
|
62 | MochiKit.MockDOM.MockElement.prototype = { | |||
|
63 | /** @id MochiKit.MockDOM.MockElement.prototype.createElement */ | |||
|
64 | createElement: function (tagName) { | |||
|
65 | return new MochiKit.MockDOM.MockElement(tagName, null, this.nodeType == 9 ? this : this.ownerDocument); | |||
|
66 | }, | |||
|
67 | /** @id MochiKit.MockDOM.MockElement.prototype.createTextNode */ | |||
|
68 | createTextNode: function (text) { | |||
|
69 | return new MochiKit.MockDOM.MockElement("text", text, this.nodeType == 9 ? this : this.ownerDocument); | |||
|
70 | }, | |||
|
71 | /** @id MochiKit.MockDOM.MockElement.prototype.setAttribute */ | |||
|
72 | setAttribute: function (name, value) { | |||
|
73 | this[name] = value; | |||
|
74 | }, | |||
|
75 | /** @id MochiKit.MockDOM.MockElement.prototype.getAttribute */ | |||
|
76 | getAttribute: function (name) { | |||
|
77 | return this[name]; | |||
|
78 | }, | |||
|
79 | /** @id MochiKit.MockDOM.MockElement.prototype.appendChild */ | |||
|
80 | appendChild: function (child) { | |||
|
81 | this.childNodes.push(child); | |||
|
82 | }, | |||
|
83 | /** @id MochiKit.MockDOM.MockElement.prototype.toString */ | |||
|
84 | toString: function () { | |||
|
85 | return "MockElement(" + this.tagName + ")"; | |||
|
86 | }, | |||
|
87 | /** @id MochiKit.MockDOM.MockElement.prototype.getElementsByTagName */ | |||
|
88 | getElementsByTagName: function (tagName) { | |||
|
89 | var foundElements = []; | |||
|
90 | MochiKit.Base.nodeWalk(this, function(node){ | |||
|
91 | if (tagName == '*' || tagName == node.tagName) { | |||
|
92 | foundElements.push(node); | |||
|
93 | return node.childNodes; | |||
|
94 | } | |||
|
95 | }); | |||
|
96 | return foundElements; | |||
|
97 | } | |||
|
98 | }; | |||
|
99 | ||||
|
100 | /** @id MochiKit.MockDOM.EXPORT_OK */ | |||
|
101 | MochiKit.MockDOM.EXPORT_OK = [ | |||
|
102 | "mockElement", | |||
|
103 | "createDocument" | |||
|
104 | ]; | |||
|
105 | ||||
|
106 | /** @id MochiKit.MockDOM.EXPORT */ | |||
|
107 | MochiKit.MockDOM.EXPORT = [ | |||
|
108 | "document" | |||
|
109 | ]; | |||
|
110 | ||||
|
111 | MochiKit.MockDOM.__new__ = function () { | |||
|
112 | this.document = this.createDocument(); | |||
|
113 | }; | |||
|
114 | ||||
|
115 | MochiKit.MockDOM.__new__(); |
@@ -0,0 +1,258 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.Position 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005-2006 Bob Ippolito and others. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.Position'); | |||
|
13 | dojo.require('MochiKit.Base'); | |||
|
14 | dojo.require('MochiKit.DOM'); | |||
|
15 | dojo.require('MochiKit.Style'); | |||
|
16 | } | |||
|
17 | if (typeof(JSAN) != 'undefined') { | |||
|
18 | JSAN.use('MochiKit.Base', []); | |||
|
19 | JSAN.use('MochiKit.DOM', []); | |||
|
20 | JSAN.use('MochiKit.Style', []); | |||
|
21 | } | |||
|
22 | ||||
|
23 | try { | |||
|
24 | if (typeof(MochiKit.Base) == 'undefined' || | |||
|
25 | typeof(MochiKit.Style) == 'undefined' || | |||
|
26 | typeof(MochiKit.DOM) == 'undefined') { | |||
|
27 | throw ''; | |||
|
28 | } | |||
|
29 | } catch (e) { | |||
|
30 | throw 'MochiKit.Style depends on MochiKit.Base, MochiKit.DOM, and MochiKit.Style!'; | |||
|
31 | } | |||
|
32 | ||||
|
33 | if (typeof(MochiKit.Position) == 'undefined') { | |||
|
34 | MochiKit.Position = {}; | |||
|
35 | } | |||
|
36 | ||||
|
37 | MochiKit.Position.NAME = 'MochiKit.Position'; | |||
|
38 | MochiKit.Position.VERSION = '1.4'; | |||
|
39 | MochiKit.Position.__repr__ = function () { | |||
|
40 | return '[' + this.NAME + ' ' + this.VERSION + ']'; | |||
|
41 | }; | |||
|
42 | MochiKit.Position.toString = function () { | |||
|
43 | return this.__repr__(); | |||
|
44 | }; | |||
|
45 | ||||
|
46 | MochiKit.Position.EXPORT_OK = []; | |||
|
47 | ||||
|
48 | MochiKit.Position.EXPORT = [ | |||
|
49 | ]; | |||
|
50 | ||||
|
51 | ||||
|
52 | MochiKit.Base.update(MochiKit.Position, { | |||
|
53 | // set to true if needed, warning: firefox performance problems | |||
|
54 | // NOT neeeded for page scrolling, only if draggable contained in | |||
|
55 | // scrollable elements | |||
|
56 | includeScrollOffsets: false, | |||
|
57 | ||||
|
58 | /** @id MochiKit.Position.prepare */ | |||
|
59 | prepare: function () { | |||
|
60 | var deltaX = window.pageXOffset | |||
|
61 | || document.documentElement.scrollLeft | |||
|
62 | || document.body.scrollLeft | |||
|
63 | || 0; | |||
|
64 | var deltaY = window.pageYOffset | |||
|
65 | || document.documentElement.scrollTop | |||
|
66 | || document.body.scrollTop | |||
|
67 | || 0; | |||
|
68 | this.windowOffset = new MochiKit.Style.Coordinates(deltaX, deltaY); | |||
|
69 | }, | |||
|
70 | ||||
|
71 | /** @id MochiKit.Position.cumulativeOffset */ | |||
|
72 | cumulativeOffset: function (element) { | |||
|
73 | var valueT = 0; | |||
|
74 | var valueL = 0; | |||
|
75 | do { | |||
|
76 | valueT += element.offsetTop || 0; | |||
|
77 | valueL += element.offsetLeft || 0; | |||
|
78 | element = element.offsetParent; | |||
|
79 | } while (element); | |||
|
80 | return new MochiKit.Style.Coordinates(valueL, valueT); | |||
|
81 | }, | |||
|
82 | ||||
|
83 | /** @id MochiKit.Position.realOffset */ | |||
|
84 | realOffset: function (element) { | |||
|
85 | var valueT = 0; | |||
|
86 | var valueL = 0; | |||
|
87 | do { | |||
|
88 | valueT += element.scrollTop || 0; | |||
|
89 | valueL += element.scrollLeft || 0; | |||
|
90 | element = element.parentNode; | |||
|
91 | } while (element); | |||
|
92 | return new MochiKit.Style.Coordinates(valueL, valueT); | |||
|
93 | }, | |||
|
94 | ||||
|
95 | /** @id MochiKit.Position.within */ | |||
|
96 | within: function (element, x, y) { | |||
|
97 | if (this.includeScrollOffsets) { | |||
|
98 | return this.withinIncludingScrolloffsets(element, x, y); | |||
|
99 | } | |||
|
100 | this.xcomp = x; | |||
|
101 | this.ycomp = y; | |||
|
102 | this.offset = this.cumulativeOffset(element); | |||
|
103 | if (element.style.position == "fixed") { | |||
|
104 | this.offset.x += this.windowOffset.x; | |||
|
105 | this.offset.y += this.windowOffset.y; | |||
|
106 | } | |||
|
107 | ||||
|
108 | return (y >= this.offset.y && | |||
|
109 | y < this.offset.y + element.offsetHeight && | |||
|
110 | x >= this.offset.x && | |||
|
111 | x < this.offset.x + element.offsetWidth); | |||
|
112 | }, | |||
|
113 | ||||
|
114 | /** @id MochiKit.Position.withinIncludingScrolloffsets */ | |||
|
115 | withinIncludingScrolloffsets: function (element, x, y) { | |||
|
116 | var offsetcache = this.realOffset(element); | |||
|
117 | ||||
|
118 | this.xcomp = x + offsetcache.x - this.windowOffset.x; | |||
|
119 | this.ycomp = y + offsetcache.y - this.windowOffset.y; | |||
|
120 | this.offset = this.cumulativeOffset(element); | |||
|
121 | ||||
|
122 | return (this.ycomp >= this.offset.y && | |||
|
123 | this.ycomp < this.offset.y + element.offsetHeight && | |||
|
124 | this.xcomp >= this.offset.x && | |||
|
125 | this.xcomp < this.offset.x + element.offsetWidth); | |||
|
126 | }, | |||
|
127 | ||||
|
128 | // within must be called directly before | |||
|
129 | /** @id MochiKit.Position.overlap */ | |||
|
130 | overlap: function (mode, element) { | |||
|
131 | if (!mode) { | |||
|
132 | return 0; | |||
|
133 | } | |||
|
134 | if (mode == 'vertical') { | |||
|
135 | return ((this.offset.y + element.offsetHeight) - this.ycomp) / | |||
|
136 | element.offsetHeight; | |||
|
137 | } | |||
|
138 | if (mode == 'horizontal') { | |||
|
139 | return ((this.offset.x + element.offsetWidth) - this.xcomp) / | |||
|
140 | element.offsetWidth; | |||
|
141 | } | |||
|
142 | }, | |||
|
143 | ||||
|
144 | /** @id MochiKit.Position.absolutize */ | |||
|
145 | absolutize: function (element) { | |||
|
146 | element = MochiKit.DOM.getElement(element); | |||
|
147 | if (element.style.position == 'absolute') { | |||
|
148 | return; | |||
|
149 | } | |||
|
150 | MochiKit.Position.prepare(); | |||
|
151 | ||||
|
152 | var offsets = MochiKit.Position.positionedOffset(element); | |||
|
153 | var width = element.clientWidth; | |||
|
154 | var height = element.clientHeight; | |||
|
155 | ||||
|
156 | var oldStyle = { | |||
|
157 | 'position': element.style.position, | |||
|
158 | 'left': offsets.x - parseFloat(element.style.left || 0), | |||
|
159 | 'top': offsets.y - parseFloat(element.style.top || 0), | |||
|
160 | 'width': element.style.width, | |||
|
161 | 'height': element.style.height | |||
|
162 | }; | |||
|
163 | ||||
|
164 | element.style.position = 'absolute'; | |||
|
165 | element.style.top = offsets.y + 'px'; | |||
|
166 | element.style.left = offsets.x + 'px'; | |||
|
167 | element.style.width = width + 'px'; | |||
|
168 | element.style.height = height + 'px'; | |||
|
169 | ||||
|
170 | return oldStyle; | |||
|
171 | }, | |||
|
172 | ||||
|
173 | /** @id MochiKit.Position.positionedOffset */ | |||
|
174 | positionedOffset: function (element) { | |||
|
175 | var valueT = 0, valueL = 0; | |||
|
176 | do { | |||
|
177 | valueT += element.offsetTop || 0; | |||
|
178 | valueL += element.offsetLeft || 0; | |||
|
179 | element = element.offsetParent; | |||
|
180 | if (element) { | |||
|
181 | p = MochiKit.Style.getStyle(element, 'position'); | |||
|
182 | if (p == 'relative' || p == 'absolute') { | |||
|
183 | break; | |||
|
184 | } | |||
|
185 | } | |||
|
186 | } while (element); | |||
|
187 | return new MochiKit.Style.Coordinates(valueL, valueT); | |||
|
188 | }, | |||
|
189 | ||||
|
190 | /** @id MochiKit.Position.relativize */ | |||
|
191 | relativize: function (element, oldPos) { | |||
|
192 | element = MochiKit.DOM.getElement(element); | |||
|
193 | if (element.style.position == 'relative') { | |||
|
194 | return; | |||
|
195 | } | |||
|
196 | MochiKit.Position.prepare(); | |||
|
197 | ||||
|
198 | var top = parseFloat(element.style.top || 0) - | |||
|
199 | (oldPos['top'] || 0); | |||
|
200 | var left = parseFloat(element.style.left || 0) - | |||
|
201 | (oldPos['left'] || 0); | |||
|
202 | ||||
|
203 | element.style.position = oldPos['position']; | |||
|
204 | element.style.top = top + 'px'; | |||
|
205 | element.style.left = left + 'px'; | |||
|
206 | element.style.width = oldPos['width']; | |||
|
207 | element.style.height = oldPos['height']; | |||
|
208 | }, | |||
|
209 | ||||
|
210 | /** @id MochiKit.Position.clone */ | |||
|
211 | clone: function (source, target) { | |||
|
212 | source = MochiKit.DOM.getElement(source); | |||
|
213 | target = MochiKit.DOM.getElement(target); | |||
|
214 | target.style.position = 'absolute'; | |||
|
215 | var offsets = this.cumulativeOffset(source); | |||
|
216 | target.style.top = offsets.y + 'px'; | |||
|
217 | target.style.left = offsets.x + 'px'; | |||
|
218 | target.style.width = source.offsetWidth + 'px'; | |||
|
219 | target.style.height = source.offsetHeight + 'px'; | |||
|
220 | }, | |||
|
221 | ||||
|
222 | /** @id MochiKit.Position.page */ | |||
|
223 | page: function (forElement) { | |||
|
224 | var valueT = 0; | |||
|
225 | var valueL = 0; | |||
|
226 | ||||
|
227 | var element = forElement; | |||
|
228 | do { | |||
|
229 | valueT += element.offsetTop || 0; | |||
|
230 | valueL += element.offsetLeft || 0; | |||
|
231 | ||||
|
232 | // Safari fix | |||
|
233 | if (element.offsetParent == document.body && MochiKit.Style.getStyle(element, 'position') == 'absolute') { | |||
|
234 | break; | |||
|
235 | } | |||
|
236 | } while (element = element.offsetParent); | |||
|
237 | ||||
|
238 | element = forElement; | |||
|
239 | do { | |||
|
240 | valueT -= element.scrollTop || 0; | |||
|
241 | valueL -= element.scrollLeft || 0; | |||
|
242 | } while (element = element.parentNode); | |||
|
243 | ||||
|
244 | return new MochiKit.Style.Coordinates(valueL, valueT); | |||
|
245 | } | |||
|
246 | }); | |||
|
247 | ||||
|
248 | MochiKit.Position.__new__ = function (win) { | |||
|
249 | var m = MochiKit.Base; | |||
|
250 | this.EXPORT_TAGS = { | |||
|
251 | ':common': this.EXPORT, | |||
|
252 | ':all': m.concat(this.EXPORT, this.EXPORT_OK) | |||
|
253 | }; | |||
|
254 | ||||
|
255 | m.nameFunctions(this); | |||
|
256 | }; | |||
|
257 | ||||
|
258 | MochiKit.Position.__new__(this); No newline at end of file |
@@ -0,0 +1,431 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.Selector 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito and others. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.Selector'); | |||
|
13 | dojo.require('MochiKit.Base'); | |||
|
14 | dojo.require('MochiKit.DOM'); | |||
|
15 | dojo.require('MochiKit.Iter'); | |||
|
16 | } | |||
|
17 | ||||
|
18 | if (typeof(JSAN) != 'undefined') { | |||
|
19 | JSAN.use("MochiKit.Base", []); | |||
|
20 | JSAN.use("MochiKit.DOM", []); | |||
|
21 | JSAN.use("MochiKit.Iter", []); | |||
|
22 | } | |||
|
23 | ||||
|
24 | try { | |||
|
25 | if (typeof(MochiKit.Base) === 'undefined' || | |||
|
26 | typeof(MochiKit.DOM) === 'undefined' || | |||
|
27 | typeof(MochiKit.Iter) === 'undefined') { | |||
|
28 | throw ""; | |||
|
29 | } | |||
|
30 | } catch (e) { | |||
|
31 | throw "MochiKit.Selector depends on MochiKit.Base, MochiKit.DOM and MochiKit.Iter!"; | |||
|
32 | } | |||
|
33 | ||||
|
34 | if (typeof(MochiKit.Selector) == 'undefined') { | |||
|
35 | MochiKit.Selector = {}; | |||
|
36 | } | |||
|
37 | ||||
|
38 | MochiKit.Selector.NAME = "MochiKit.Selector"; | |||
|
39 | ||||
|
40 | MochiKit.Selector.VERSION = "1.4"; | |||
|
41 | ||||
|
42 | MochiKit.Selector.__repr__ = function () { | |||
|
43 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
44 | }; | |||
|
45 | ||||
|
46 | MochiKit.Selector.toString = function () { | |||
|
47 | return this.__repr__(); | |||
|
48 | }; | |||
|
49 | ||||
|
50 | MochiKit.Selector.EXPORT = [ | |||
|
51 | "Selector", | |||
|
52 | "findChildElements", | |||
|
53 | "findDocElements", | |||
|
54 | "$$" | |||
|
55 | ]; | |||
|
56 | ||||
|
57 | MochiKit.Selector.EXPORT_OK = [ | |||
|
58 | ]; | |||
|
59 | ||||
|
60 | MochiKit.Selector.Selector = function (expression) { | |||
|
61 | this.params = {classNames: [], pseudoClassNames: []}; | |||
|
62 | this.expression = expression.toString().replace(/(^\s+|\s+$)/g, ''); | |||
|
63 | this.parseExpression(); | |||
|
64 | this.compileMatcher(); | |||
|
65 | }; | |||
|
66 | ||||
|
67 | MochiKit.Selector.Selector.prototype = { | |||
|
68 | /*** | |||
|
69 | ||||
|
70 | Selector class: convenient object to make CSS selections. | |||
|
71 | ||||
|
72 | ***/ | |||
|
73 | __class__: MochiKit.Selector.Selector, | |||
|
74 | ||||
|
75 | /** @id MochiKit.Selector.Selector.prototype.parseExpression */ | |||
|
76 | parseExpression: function () { | |||
|
77 | function abort(message) { | |||
|
78 | throw 'Parse error in selector: ' + message; | |||
|
79 | } | |||
|
80 | ||||
|
81 | if (this.expression == '') { | |||
|
82 | abort('empty expression'); | |||
|
83 | } | |||
|
84 | ||||
|
85 | var repr = MochiKit.Base.repr; | |||
|
86 | var params = this.params; | |||
|
87 | var expr = this.expression; | |||
|
88 | var match, modifier, clause, rest; | |||
|
89 | while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!^$*]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { | |||
|
90 | params.attributes = params.attributes || []; | |||
|
91 | params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); | |||
|
92 | expr = match[1]; | |||
|
93 | } | |||
|
94 | ||||
|
95 | if (expr == '*') { | |||
|
96 | return this.params.wildcard = true; | |||
|
97 | } | |||
|
98 | ||||
|
99 | while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+(?:\([^)]*\))?)(.*)/i)) { | |||
|
100 | modifier = match[1]; | |||
|
101 | clause = match[2]; | |||
|
102 | rest = match[3]; | |||
|
103 | switch (modifier) { | |||
|
104 | case '#': | |||
|
105 | params.id = clause; | |||
|
106 | break; | |||
|
107 | case '.': | |||
|
108 | params.classNames.push(clause); | |||
|
109 | break; | |||
|
110 | case ':': | |||
|
111 | params.pseudoClassNames.push(clause); | |||
|
112 | break; | |||
|
113 | case '': | |||
|
114 | case undefined: | |||
|
115 | params.tagName = clause.toUpperCase(); | |||
|
116 | break; | |||
|
117 | default: | |||
|
118 | abort(repr(expr)); | |||
|
119 | } | |||
|
120 | expr = rest; | |||
|
121 | } | |||
|
122 | ||||
|
123 | if (expr.length > 0) { | |||
|
124 | abort(repr(expr)); | |||
|
125 | } | |||
|
126 | }, | |||
|
127 | ||||
|
128 | /** @id MochiKit.Selector.Selector.prototype.buildMatchExpression */ | |||
|
129 | buildMatchExpression: function () { | |||
|
130 | var repr = MochiKit.Base.repr; | |||
|
131 | var params = this.params; | |||
|
132 | var conditions = []; | |||
|
133 | var clause, i; | |||
|
134 | ||||
|
135 | function childElements(element) { | |||
|
136 | return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, " + element + ".childNodes)"; | |||
|
137 | } | |||
|
138 | ||||
|
139 | if (params.wildcard) { | |||
|
140 | conditions.push('true'); | |||
|
141 | } | |||
|
142 | if (clause = params.id) { | |||
|
143 | conditions.push('element.id == ' + repr(clause)); | |||
|
144 | } | |||
|
145 | if (clause = params.tagName) { | |||
|
146 | conditions.push('element.tagName.toUpperCase() == ' + repr(clause)); | |||
|
147 | } | |||
|
148 | if ((clause = params.classNames).length > 0) { | |||
|
149 | for (i = 0; i < clause.length; i++) { | |||
|
150 | conditions.push('MochiKit.DOM.hasElementClass(element, ' + repr(clause[i]) + ')'); | |||
|
151 | } | |||
|
152 | } | |||
|
153 | if ((clause = params.pseudoClassNames).length > 0) { | |||
|
154 | for (i = 0; i < clause.length; i++) { | |||
|
155 | var match = clause[i].match(/^([^(]+)(?:\((.*)\))?$/); | |||
|
156 | var pseudoClass = match[1]; | |||
|
157 | var pseudoClassArgument = match[2]; | |||
|
158 | switch (pseudoClass) { | |||
|
159 | case 'root': | |||
|
160 | conditions.push('element.nodeType == 9 || element === element.ownerDocument.documentElement'); break; | |||
|
161 | case 'nth-child': | |||
|
162 | case 'nth-last-child': | |||
|
163 | case 'nth-of-type': | |||
|
164 | case 'nth-last-of-type': | |||
|
165 | match = pseudoClassArgument.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/); | |||
|
166 | if (!match) { | |||
|
167 | throw "Invalid argument to pseudo element nth-child: " + pseudoClassArgument; | |||
|
168 | } | |||
|
169 | var a, b; | |||
|
170 | if (match[0] == 'odd') { | |||
|
171 | a = 2; | |||
|
172 | b = 1; | |||
|
173 | } else if (match[0] == 'even') { | |||
|
174 | a = 2; | |||
|
175 | b = 0; | |||
|
176 | } else { | |||
|
177 | a = match[2] && parseInt(match) || null; | |||
|
178 | b = parseInt(match[3]); | |||
|
179 | } | |||
|
180 | conditions.push('this.nthChild(element,' + a + ',' + b | |||
|
181 | + ',' + !!pseudoClass.match('^nth-last') // Reverse | |||
|
182 | + ',' + !!pseudoClass.match('of-type$') // Restrict to same tagName | |||
|
183 | + ')'); | |||
|
184 | break; | |||
|
185 | case 'first-child': | |||
|
186 | conditions.push('this.nthChild(element, null, 1)'); | |||
|
187 | break; | |||
|
188 | case 'last-child': | |||
|
189 | conditions.push('this.nthChild(element, null, 1, true)'); | |||
|
190 | break; | |||
|
191 | case 'first-of-type': | |||
|
192 | conditions.push('this.nthChild(element, null, 1, false, true)'); | |||
|
193 | break; | |||
|
194 | case 'last-of-type': | |||
|
195 | conditions.push('this.nthChild(element, null, 1, true, true)'); | |||
|
196 | break; | |||
|
197 | case 'only-child': | |||
|
198 | conditions.push(childElements('element.parentNode') + '.length == 1'); | |||
|
199 | break; | |||
|
200 | case 'only-of-type': | |||
|
201 | conditions.push('MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, ' + childElements('element.parentNode') + ').length == 1'); | |||
|
202 | break; | |||
|
203 | case 'empty': | |||
|
204 | conditions.push('element.childNodes.length == 0'); | |||
|
205 | break; | |||
|
206 | case 'enabled': | |||
|
207 | conditions.push('(this.isUIElement(element) && element.disabled === false)'); | |||
|
208 | break; | |||
|
209 | case 'disabled': | |||
|
210 | conditions.push('(this.isUIElement(element) && element.disabled === true)'); | |||
|
211 | break; | |||
|
212 | case 'checked': | |||
|
213 | conditions.push('(this.isUIElement(element) && element.checked === true)'); | |||
|
214 | break; | |||
|
215 | case 'not': | |||
|
216 | var subselector = new MochiKit.Selector.Selector(pseudoClassArgument); | |||
|
217 | conditions.push('!( ' + subselector.buildMatchExpression() + ')') | |||
|
218 | break; | |||
|
219 | } | |||
|
220 | } | |||
|
221 | } | |||
|
222 | if (clause = params.attributes) { | |||
|
223 | MochiKit.Base.map(function (attribute) { | |||
|
224 | var value = 'MochiKit.DOM.getNodeAttribute(element, ' + repr(attribute.name) + ')'; | |||
|
225 | var splitValueBy = function (delimiter) { | |||
|
226 | return value + '.split(' + repr(delimiter) + ')'; | |||
|
227 | } | |||
|
228 | ||||
|
229 | switch (attribute.operator) { | |||
|
230 | case '=': | |||
|
231 | conditions.push(value + ' == ' + repr(attribute.value)); | |||
|
232 | break; | |||
|
233 | case '~=': | |||
|
234 | conditions.push(value + ' && MochiKit.Base.findValue(' + splitValueBy(' ') + ', ' + repr(attribute.value) + ') > -1'); | |||
|
235 | break; | |||
|
236 | case '^=': | |||
|
237 | conditions.push(value + '.substring(0, ' + attribute.value.length + ') == ' + repr(attribute.value)); | |||
|
238 | break; | |||
|
239 | case '$=': | |||
|
240 | conditions.push(value + '.substring(' + value + '.length - ' + attribute.value.length + ') == ' + repr(attribute.value)); | |||
|
241 | break; | |||
|
242 | case '*=': | |||
|
243 | conditions.push(value + '.match(' + repr(attribute.value) + ')'); | |||
|
244 | break; | |||
|
245 | case '|=': | |||
|
246 | conditions.push( | |||
|
247 | value + ' && ' + splitValueBy('-') + '[0].toUpperCase() == ' + repr(attribute.value.toUpperCase()) | |||
|
248 | ); | |||
|
249 | break; | |||
|
250 | case '!=': | |||
|
251 | conditions.push(value + ' != ' + repr(attribute.value)); | |||
|
252 | break; | |||
|
253 | case '': | |||
|
254 | case undefined: | |||
|
255 | conditions.push(value + ' != null'); | |||
|
256 | break; | |||
|
257 | default: | |||
|
258 | throw 'Unknown operator ' + attribute.operator + ' in selector'; | |||
|
259 | } | |||
|
260 | }, clause); | |||
|
261 | } | |||
|
262 | ||||
|
263 | return conditions.join(' && '); | |||
|
264 | }, | |||
|
265 | ||||
|
266 | /** @id MochiKit.Selector.Selector.prototype.compileMatcher */ | |||
|
267 | compileMatcher: function () { | |||
|
268 | this.match = new Function('element', 'if (!element.tagName) return false; \ | |||
|
269 | return ' + this.buildMatchExpression()); | |||
|
270 | }, | |||
|
271 | ||||
|
272 | /** @id MochiKit.Selector.Selector.prototype.nthChild */ | |||
|
273 | nthChild: function (element, a, b, reverse, sametag){ | |||
|
274 | var siblings = MochiKit.Base.filter(function (node) { | |||
|
275 | return node.nodeType == 1; | |||
|
276 | }, element.parentNode.childNodes); | |||
|
277 | if (sametag) { | |||
|
278 | siblings = MochiKit.Base.filter(function (node) { | |||
|
279 | return node.tagName == element.tagName; | |||
|
280 | }, siblings); | |||
|
281 | } | |||
|
282 | if (reverse) { | |||
|
283 | siblings = MochiKit.Iter.reversed(siblings); | |||
|
284 | } | |||
|
285 | if (a) { | |||
|
286 | var actualIndex = MochiKit.Base.findIdentical(siblings, element); | |||
|
287 | return ((actualIndex + 1 - b) / a) % 1 == 0; | |||
|
288 | } else { | |||
|
289 | return b == MochiKit.Base.findIdentical(siblings, element) + 1; | |||
|
290 | } | |||
|
291 | }, | |||
|
292 | ||||
|
293 | /** @id MochiKit.Selector.Selector.prototype.isUIElement */ | |||
|
294 | isUIElement: function (element) { | |||
|
295 | return MochiKit.Base.findValue(['input', 'button', 'select', 'option', 'textarea', 'object'], | |||
|
296 | element.tagName.toLowerCase()) > -1; | |||
|
297 | }, | |||
|
298 | ||||
|
299 | /** @id MochiKit.Selector.Selector.prototype.findElements */ | |||
|
300 | findElements: function (scope, axis) { | |||
|
301 | var element; | |||
|
302 | ||||
|
303 | if (axis == undefined) { | |||
|
304 | axis = ""; | |||
|
305 | } | |||
|
306 | ||||
|
307 | function inScope(element, scope) { | |||
|
308 | if (axis == "") { | |||
|
309 | return MochiKit.DOM.isChildNode(element, scope); | |||
|
310 | } else if (axis == ">") { | |||
|
311 | return element.parentNode == scope; | |||
|
312 | } else if (axis == "+") { | |||
|
313 | return element == nextSiblingElement(scope); | |||
|
314 | } else if (axis == "~") { | |||
|
315 | var sibling = scope; | |||
|
316 | while (sibling = nextSiblingElement(sibling)) { | |||
|
317 | if (element == sibling) { | |||
|
318 | return true; | |||
|
319 | } | |||
|
320 | } | |||
|
321 | return false; | |||
|
322 | } else { | |||
|
323 | throw "Invalid axis: " + axis; | |||
|
324 | } | |||
|
325 | } | |||
|
326 | ||||
|
327 | if (element = MochiKit.DOM.getElement(this.params.id)) { | |||
|
328 | if (this.match(element)) { | |||
|
329 | if (!scope || inScope(element, scope)) { | |||
|
330 | return [element]; | |||
|
331 | } | |||
|
332 | } | |||
|
333 | } | |||
|
334 | ||||
|
335 | function nextSiblingElement(node) { | |||
|
336 | node = node.nextSibling; | |||
|
337 | while (node && node.nodeType != 1) { | |||
|
338 | node = node.nextSibling; | |||
|
339 | } | |||
|
340 | return node; | |||
|
341 | } | |||
|
342 | ||||
|
343 | if (axis == "") { | |||
|
344 | scope = (scope || MochiKit.DOM.currentDocument()).getElementsByTagName(this.params.tagName || '*'); | |||
|
345 | } else if (axis == ">") { | |||
|
346 | if (!scope) { | |||
|
347 | throw "> combinator not allowed without preceeding expression"; | |||
|
348 | } | |||
|
349 | scope = MochiKit.Base.filter(function (node) { | |||
|
350 | return node.nodeType == 1; | |||
|
351 | }, scope.childNodes); | |||
|
352 | } else if (axis == "+") { | |||
|
353 | if (!scope) { | |||
|
354 | throw "+ combinator not allowed without preceeding expression"; | |||
|
355 | } | |||
|
356 | scope = nextSiblingElement(scope) && [nextSiblingElement(scope)]; | |||
|
357 | } else if (axis == "~") { | |||
|
358 | if (!scope) { | |||
|
359 | throw "~ combinator not allowed without preceeding expression"; | |||
|
360 | } | |||
|
361 | var newscope = []; | |||
|
362 | while (nextSiblingElement(scope)) { | |||
|
363 | scope = nextSiblingElement(scope); | |||
|
364 | newscope.push(scope); | |||
|
365 | } | |||
|
366 | scope = newscope; | |||
|
367 | } | |||
|
368 | ||||
|
369 | if (!scope) { | |||
|
370 | return []; | |||
|
371 | } | |||
|
372 | ||||
|
373 | var results = MochiKit.Base.filter(MochiKit.Base.bind(function (scopeElt) { | |||
|
374 | return this.match(scopeElt); | |||
|
375 | }, this), scope); | |||
|
376 | ||||
|
377 | return results; | |||
|
378 | }, | |||
|
379 | ||||
|
380 | /** @id MochiKit.Selector.Selector.prototype.repr */ | |||
|
381 | repr: function () { | |||
|
382 | return 'Selector(' + this.expression + ')'; | |||
|
383 | }, | |||
|
384 | ||||
|
385 | toString: MochiKit.Base.forwardCall("repr") | |||
|
386 | }; | |||
|
387 | ||||
|
388 | MochiKit.Base.update(MochiKit.Selector, { | |||
|
389 | ||||
|
390 | /** @id MochiKit.Selector.findChildElements */ | |||
|
391 | findChildElements: function (element, expressions) { | |||
|
392 | return MochiKit.Base.flattenArray(MochiKit.Base.map(function (expression) { | |||
|
393 | var nextScope = ""; | |||
|
394 | return MochiKit.Iter.reduce(function (results, expr) { | |||
|
395 | if (match = expr.match(/^[>+~]$/)) { | |||
|
396 | nextScope = match[0]; | |||
|
397 | return results; | |||
|
398 | } else { | |||
|
399 | var selector = new MochiKit.Selector.Selector(expr); | |||
|
400 | var elements = MochiKit.Iter.reduce(function (elements, result) { | |||
|
401 | return MochiKit.Base.extend(elements, selector.findElements(result || element, nextScope)); | |||
|
402 | }, results, []); | |||
|
403 | nextScope = ""; | |||
|
404 | return elements; | |||
|
405 | } | |||
|
406 | }, expression.replace(/(^\s+|\s+$)/g, '').split(/\s+/), [null]); | |||
|
407 | }, expressions)); | |||
|
408 | }, | |||
|
409 | ||||
|
410 | findDocElements: function () { | |||
|
411 | return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(), arguments); | |||
|
412 | }, | |||
|
413 | ||||
|
414 | __new__: function () { | |||
|
415 | var m = MochiKit.Base; | |||
|
416 | ||||
|
417 | this.$$ = this.findDocElements; | |||
|
418 | ||||
|
419 | this.EXPORT_TAGS = { | |||
|
420 | ":common": this.EXPORT, | |||
|
421 | ":all": m.concat(this.EXPORT, this.EXPORT_OK) | |||
|
422 | }; | |||
|
423 | ||||
|
424 | m.nameFunctions(this); | |||
|
425 | } | |||
|
426 | }); | |||
|
427 | ||||
|
428 | MochiKit.Selector.__new__(); | |||
|
429 | ||||
|
430 | MochiKit.Base._exportSymbols(this, MochiKit.Selector); | |||
|
431 |
This diff has been collapsed as it changes many lines, (903 lines changed) Show them Hide them | |||||
@@ -0,0 +1,903 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.Signal 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2006 Jonathan Gardner, Beau Hartshorne, Bob Ippolito. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.Signal'); | |||
|
13 | dojo.require('MochiKit.Base'); | |||
|
14 | dojo.require('MochiKit.DOM'); | |||
|
15 | dojo.require('MochiKit.Style'); | |||
|
16 | } | |||
|
17 | if (typeof(JSAN) != 'undefined') { | |||
|
18 | JSAN.use('MochiKit.Base', []); | |||
|
19 | JSAN.use('MochiKit.DOM', []); | |||
|
20 | JSAN.use('MochiKit.Style', []); | |||
|
21 | } | |||
|
22 | ||||
|
23 | try { | |||
|
24 | if (typeof(MochiKit.Base) == 'undefined') { | |||
|
25 | throw ''; | |||
|
26 | } | |||
|
27 | } catch (e) { | |||
|
28 | throw 'MochiKit.Signal depends on MochiKit.Base!'; | |||
|
29 | } | |||
|
30 | ||||
|
31 | try { | |||
|
32 | if (typeof(MochiKit.DOM) == 'undefined') { | |||
|
33 | throw ''; | |||
|
34 | } | |||
|
35 | } catch (e) { | |||
|
36 | throw 'MochiKit.Signal depends on MochiKit.DOM!'; | |||
|
37 | } | |||
|
38 | ||||
|
39 | try { | |||
|
40 | if (typeof(MochiKit.Style) == 'undefined') { | |||
|
41 | throw ''; | |||
|
42 | } | |||
|
43 | } catch (e) { | |||
|
44 | throw 'MochiKit.Signal depends on MochiKit.Style!'; | |||
|
45 | } | |||
|
46 | ||||
|
47 | if (typeof(MochiKit.Signal) == 'undefined') { | |||
|
48 | MochiKit.Signal = {}; | |||
|
49 | } | |||
|
50 | ||||
|
51 | MochiKit.Signal.NAME = 'MochiKit.Signal'; | |||
|
52 | MochiKit.Signal.VERSION = '1.4'; | |||
|
53 | ||||
|
54 | MochiKit.Signal._observers = []; | |||
|
55 | ||||
|
56 | /** @id MochiKit.Signal.Event */ | |||
|
57 | MochiKit.Signal.Event = function (src, e) { | |||
|
58 | this._event = e || window.event; | |||
|
59 | this._src = src; | |||
|
60 | }; | |||
|
61 | ||||
|
62 | MochiKit.Base.update(MochiKit.Signal.Event.prototype, { | |||
|
63 | ||||
|
64 | __repr__: function () { | |||
|
65 | var repr = MochiKit.Base.repr; | |||
|
66 | var str = '{event(): ' + repr(this.event()) + | |||
|
67 | ', src(): ' + repr(this.src()) + | |||
|
68 | ', type(): ' + repr(this.type()) + | |||
|
69 | ', target(): ' + repr(this.target()); | |||
|
70 | ||||
|
71 | if (this.type() && | |||
|
72 | this.type().indexOf('key') === 0 || | |||
|
73 | this.type().indexOf('mouse') === 0 || | |||
|
74 | this.type().indexOf('click') != -1 || | |||
|
75 | this.type() == 'contextmenu') { | |||
|
76 | str += ', modifier(): ' + '{alt: ' + repr(this.modifier().alt) + | |||
|
77 | ', ctrl: ' + repr(this.modifier().ctrl) + | |||
|
78 | ', meta: ' + repr(this.modifier().meta) + | |||
|
79 | ', shift: ' + repr(this.modifier().shift) + | |||
|
80 | ', any: ' + repr(this.modifier().any) + '}'; | |||
|
81 | } | |||
|
82 | ||||
|
83 | if (this.type() && this.type().indexOf('key') === 0) { | |||
|
84 | str += ', key(): {code: ' + repr(this.key().code) + | |||
|
85 | ', string: ' + repr(this.key().string) + '}'; | |||
|
86 | } | |||
|
87 | ||||
|
88 | if (this.type() && ( | |||
|
89 | this.type().indexOf('mouse') === 0 || | |||
|
90 | this.type().indexOf('click') != -1 || | |||
|
91 | this.type() == 'contextmenu')) { | |||
|
92 | ||||
|
93 | str += ', mouse(): {page: ' + repr(this.mouse().page) + | |||
|
94 | ', client: ' + repr(this.mouse().client); | |||
|
95 | ||||
|
96 | if (this.type() != 'mousemove') { | |||
|
97 | str += ', button: {left: ' + repr(this.mouse().button.left) + | |||
|
98 | ', middle: ' + repr(this.mouse().button.middle) + | |||
|
99 | ', right: ' + repr(this.mouse().button.right) + '}}'; | |||
|
100 | } else { | |||
|
101 | str += '}'; | |||
|
102 | } | |||
|
103 | } | |||
|
104 | if (this.type() == 'mouseover' || this.type() == 'mouseout') { | |||
|
105 | str += ', relatedTarget(): ' + repr(this.relatedTarget()); | |||
|
106 | } | |||
|
107 | str += '}'; | |||
|
108 | return str; | |||
|
109 | }, | |||
|
110 | ||||
|
111 | /** @id MochiKit.Signal.Event.prototype.toString */ | |||
|
112 | toString: function () { | |||
|
113 | return this.__repr__(); | |||
|
114 | }, | |||
|
115 | ||||
|
116 | /** @id MochiKit.Signal.Event.prototype.src */ | |||
|
117 | src: function () { | |||
|
118 | return this._src; | |||
|
119 | }, | |||
|
120 | ||||
|
121 | /** @id MochiKit.Signal.Event.prototype.event */ | |||
|
122 | event: function () { | |||
|
123 | return this._event; | |||
|
124 | }, | |||
|
125 | ||||
|
126 | /** @id MochiKit.Signal.Event.prototype.type */ | |||
|
127 | type: function () { | |||
|
128 | return this._event.type || undefined; | |||
|
129 | }, | |||
|
130 | ||||
|
131 | /** @id MochiKit.Signal.Event.prototype.target */ | |||
|
132 | target: function () { | |||
|
133 | return this._event.target || this._event.srcElement; | |||
|
134 | }, | |||
|
135 | ||||
|
136 | _relatedTarget: null, | |||
|
137 | /** @id MochiKit.Signal.Event.prototype.relatedTarget */ | |||
|
138 | relatedTarget: function () { | |||
|
139 | if (this._relatedTarget !== null) { | |||
|
140 | return this._relatedTarget; | |||
|
141 | } | |||
|
142 | ||||
|
143 | var elem = null; | |||
|
144 | if (this.type() == 'mouseover') { | |||
|
145 | elem = (this._event.relatedTarget || | |||
|
146 | this._event.fromElement); | |||
|
147 | } else if (this.type() == 'mouseout') { | |||
|
148 | elem = (this._event.relatedTarget || | |||
|
149 | this._event.toElement); | |||
|
150 | } | |||
|
151 | if (elem !== null) { | |||
|
152 | this._relatedTarget = elem; | |||
|
153 | return elem; | |||
|
154 | } | |||
|
155 | ||||
|
156 | return undefined; | |||
|
157 | }, | |||
|
158 | ||||
|
159 | _modifier: null, | |||
|
160 | /** @id MochiKit.Signal.Event.prototype.modifier */ | |||
|
161 | modifier: function () { | |||
|
162 | if (this._modifier !== null) { | |||
|
163 | return this._modifier; | |||
|
164 | } | |||
|
165 | var m = {}; | |||
|
166 | m.alt = this._event.altKey; | |||
|
167 | m.ctrl = this._event.ctrlKey; | |||
|
168 | m.meta = this._event.metaKey || false; // IE and Opera punt here | |||
|
169 | m.shift = this._event.shiftKey; | |||
|
170 | m.any = m.alt || m.ctrl || m.shift || m.meta; | |||
|
171 | this._modifier = m; | |||
|
172 | return m; | |||
|
173 | }, | |||
|
174 | ||||
|
175 | _key: null, | |||
|
176 | /** @id MochiKit.Signal.Event.prototype.key */ | |||
|
177 | key: function () { | |||
|
178 | if (this._key !== null) { | |||
|
179 | return this._key; | |||
|
180 | } | |||
|
181 | var k = {}; | |||
|
182 | if (this.type() && this.type().indexOf('key') === 0) { | |||
|
183 | ||||
|
184 | /* | |||
|
185 | ||||
|
186 | If you're looking for a special key, look for it in keydown or | |||
|
187 | keyup, but never keypress. If you're looking for a Unicode | |||
|
188 | chracter, look for it with keypress, but never keyup or | |||
|
189 | keydown. | |||
|
190 | ||||
|
191 | Notes: | |||
|
192 | ||||
|
193 | FF key event behavior: | |||
|
194 | key event charCode keyCode | |||
|
195 | DOWN ku,kd 0 40 | |||
|
196 | DOWN kp 0 40 | |||
|
197 | ESC ku,kd 0 27 | |||
|
198 | ESC kp 0 27 | |||
|
199 | a ku,kd 0 65 | |||
|
200 | a kp 97 0 | |||
|
201 | shift+a ku,kd 0 65 | |||
|
202 | shift+a kp 65 0 | |||
|
203 | 1 ku,kd 0 49 | |||
|
204 | 1 kp 49 0 | |||
|
205 | shift+1 ku,kd 0 0 | |||
|
206 | shift+1 kp 33 0 | |||
|
207 | ||||
|
208 | IE key event behavior: | |||
|
209 | (IE doesn't fire keypress events for special keys.) | |||
|
210 | key event keyCode | |||
|
211 | DOWN ku,kd 40 | |||
|
212 | DOWN kp undefined | |||
|
213 | ESC ku,kd 27 | |||
|
214 | ESC kp 27 | |||
|
215 | a ku,kd 65 | |||
|
216 | a kp 97 | |||
|
217 | shift+a ku,kd 65 | |||
|
218 | shift+a kp 65 | |||
|
219 | 1 ku,kd 49 | |||
|
220 | 1 kp 49 | |||
|
221 | shift+1 ku,kd 49 | |||
|
222 | shift+1 kp 33 | |||
|
223 | ||||
|
224 | Safari key event behavior: | |||
|
225 | (Safari sets charCode and keyCode to something crazy for | |||
|
226 | special keys.) | |||
|
227 | key event charCode keyCode | |||
|
228 | DOWN ku,kd 63233 40 | |||
|
229 | DOWN kp 63233 63233 | |||
|
230 | ESC ku,kd 27 27 | |||
|
231 | ESC kp 27 27 | |||
|
232 | a ku,kd 97 65 | |||
|
233 | a kp 97 97 | |||
|
234 | shift+a ku,kd 65 65 | |||
|
235 | shift+a kp 65 65 | |||
|
236 | 1 ku,kd 49 49 | |||
|
237 | 1 kp 49 49 | |||
|
238 | shift+1 ku,kd 33 49 | |||
|
239 | shift+1 kp 33 33 | |||
|
240 | ||||
|
241 | */ | |||
|
242 | ||||
|
243 | /* look for special keys here */ | |||
|
244 | if (this.type() == 'keydown' || this.type() == 'keyup') { | |||
|
245 | k.code = this._event.keyCode; | |||
|
246 | k.string = (MochiKit.Signal._specialKeys[k.code] || | |||
|
247 | 'KEY_UNKNOWN'); | |||
|
248 | this._key = k; | |||
|
249 | return k; | |||
|
250 | ||||
|
251 | /* look for characters here */ | |||
|
252 | } else if (this.type() == 'keypress') { | |||
|
253 | ||||
|
254 | /* | |||
|
255 | ||||
|
256 | Special key behavior: | |||
|
257 | ||||
|
258 | IE: does not fire keypress events for special keys | |||
|
259 | FF: sets charCode to 0, and sets the correct keyCode | |||
|
260 | Safari: sets keyCode and charCode to something stupid | |||
|
261 | ||||
|
262 | */ | |||
|
263 | ||||
|
264 | k.code = 0; | |||
|
265 | k.string = ''; | |||
|
266 | ||||
|
267 | if (typeof(this._event.charCode) != 'undefined' && | |||
|
268 | this._event.charCode !== 0 && | |||
|
269 | !MochiKit.Signal._specialMacKeys[this._event.charCode]) { | |||
|
270 | k.code = this._event.charCode; | |||
|
271 | k.string = String.fromCharCode(k.code); | |||
|
272 | } else if (this._event.keyCode && | |||
|
273 | typeof(this._event.charCode) == 'undefined') { // IE | |||
|
274 | k.code = this._event.keyCode; | |||
|
275 | k.string = String.fromCharCode(k.code); | |||
|
276 | } | |||
|
277 | ||||
|
278 | this._key = k; | |||
|
279 | return k; | |||
|
280 | } | |||
|
281 | } | |||
|
282 | return undefined; | |||
|
283 | }, | |||
|
284 | ||||
|
285 | _mouse: null, | |||
|
286 | /** @id MochiKit.Signal.Event.prototype.mouse */ | |||
|
287 | mouse: function () { | |||
|
288 | if (this._mouse !== null) { | |||
|
289 | return this._mouse; | |||
|
290 | } | |||
|
291 | ||||
|
292 | var m = {}; | |||
|
293 | var e = this._event; | |||
|
294 | ||||
|
295 | if (this.type() && ( | |||
|
296 | this.type().indexOf('mouse') === 0 || | |||
|
297 | this.type().indexOf('click') != -1 || | |||
|
298 | this.type() == 'contextmenu')) { | |||
|
299 | ||||
|
300 | m.client = new MochiKit.Style.Coordinates(0, 0); | |||
|
301 | if (e.clientX || e.clientY) { | |||
|
302 | m.client.x = (!e.clientX || e.clientX < 0) ? 0 : e.clientX; | |||
|
303 | m.client.y = (!e.clientY || e.clientY < 0) ? 0 : e.clientY; | |||
|
304 | } | |||
|
305 | ||||
|
306 | m.page = new MochiKit.Style.Coordinates(0, 0); | |||
|
307 | if (e.pageX || e.pageY) { | |||
|
308 | m.page.x = (!e.pageX || e.pageX < 0) ? 0 : e.pageX; | |||
|
309 | m.page.y = (!e.pageY || e.pageY < 0) ? 0 : e.pageY; | |||
|
310 | } else { | |||
|
311 | /* | |||
|
312 | ||||
|
313 | The IE shortcut can be off by two. We fix it. See: | |||
|
314 | http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp | |||
|
315 | ||||
|
316 | This is similar to the method used in | |||
|
317 | MochiKit.Style.getElementPosition(). | |||
|
318 | ||||
|
319 | */ | |||
|
320 | var de = MochiKit.DOM._document.documentElement; | |||
|
321 | var b = MochiKit.DOM._document.body; | |||
|
322 | ||||
|
323 | m.page.x = e.clientX + | |||
|
324 | (de.scrollLeft || b.scrollLeft) - | |||
|
325 | (de.clientLeft || 0); | |||
|
326 | ||||
|
327 | m.page.y = e.clientY + | |||
|
328 | (de.scrollTop || b.scrollTop) - | |||
|
329 | (de.clientTop || 0); | |||
|
330 | ||||
|
331 | } | |||
|
332 | if (this.type() != 'mousemove') { | |||
|
333 | m.button = {}; | |||
|
334 | m.button.left = false; | |||
|
335 | m.button.right = false; | |||
|
336 | m.button.middle = false; | |||
|
337 | ||||
|
338 | /* we could check e.button, but which is more consistent */ | |||
|
339 | if (e.which) { | |||
|
340 | m.button.left = (e.which == 1); | |||
|
341 | m.button.middle = (e.which == 2); | |||
|
342 | m.button.right = (e.which == 3); | |||
|
343 | ||||
|
344 | /* | |||
|
345 | ||||
|
346 | Mac browsers and right click: | |||
|
347 | ||||
|
348 | - Safari doesn't fire any click events on a right | |||
|
349 | click: | |||
|
350 | http://bugs.webkit.org/show_bug.cgi?id=6595 | |||
|
351 | ||||
|
352 | - Firefox fires the event, and sets ctrlKey = true | |||
|
353 | ||||
|
354 | - Opera fires the event, and sets metaKey = true | |||
|
355 | ||||
|
356 | oncontextmenu is fired on right clicks between | |||
|
357 | browsers and across platforms. | |||
|
358 | ||||
|
359 | */ | |||
|
360 | ||||
|
361 | } else { | |||
|
362 | m.button.left = !!(e.button & 1); | |||
|
363 | m.button.right = !!(e.button & 2); | |||
|
364 | m.button.middle = !!(e.button & 4); | |||
|
365 | } | |||
|
366 | } | |||
|
367 | this._mouse = m; | |||
|
368 | return m; | |||
|
369 | } | |||
|
370 | return undefined; | |||
|
371 | }, | |||
|
372 | ||||
|
373 | /** @id MochiKit.Signal.Event.prototype.stop */ | |||
|
374 | stop: function () { | |||
|
375 | this.stopPropagation(); | |||
|
376 | this.preventDefault(); | |||
|
377 | }, | |||
|
378 | ||||
|
379 | /** @id MochiKit.Signal.Event.prototype.stopPropagation */ | |||
|
380 | stopPropagation: function () { | |||
|
381 | if (this._event.stopPropagation) { | |||
|
382 | this._event.stopPropagation(); | |||
|
383 | } else { | |||
|
384 | this._event.cancelBubble = true; | |||
|
385 | } | |||
|
386 | }, | |||
|
387 | ||||
|
388 | /** @id MochiKit.Signal.Event.prototype.preventDefault */ | |||
|
389 | preventDefault: function () { | |||
|
390 | if (this._event.preventDefault) { | |||
|
391 | this._event.preventDefault(); | |||
|
392 | } else if (this._confirmUnload === null) { | |||
|
393 | this._event.returnValue = false; | |||
|
394 | } | |||
|
395 | }, | |||
|
396 | ||||
|
397 | _confirmUnload: null, | |||
|
398 | ||||
|
399 | /** @id MochiKit.Signal.Event.prototype.confirmUnload */ | |||
|
400 | confirmUnload: function (msg) { | |||
|
401 | if (this.type() == 'beforeunload') { | |||
|
402 | this._confirmUnload = msg; | |||
|
403 | this._event.returnValue = msg; | |||
|
404 | } | |||
|
405 | } | |||
|
406 | }); | |||
|
407 | ||||
|
408 | /* Safari sets keyCode to these special values onkeypress. */ | |||
|
409 | MochiKit.Signal._specialMacKeys = { | |||
|
410 | 3: 'KEY_ENTER', | |||
|
411 | 63289: 'KEY_NUM_PAD_CLEAR', | |||
|
412 | 63276: 'KEY_PAGE_UP', | |||
|
413 | 63277: 'KEY_PAGE_DOWN', | |||
|
414 | 63275: 'KEY_END', | |||
|
415 | 63273: 'KEY_HOME', | |||
|
416 | 63234: 'KEY_ARROW_LEFT', | |||
|
417 | 63232: 'KEY_ARROW_UP', | |||
|
418 | 63235: 'KEY_ARROW_RIGHT', | |||
|
419 | 63233: 'KEY_ARROW_DOWN', | |||
|
420 | 63302: 'KEY_INSERT', | |||
|
421 | 63272: 'KEY_DELETE' | |||
|
422 | }; | |||
|
423 | ||||
|
424 | /* for KEY_F1 - KEY_F12 */ | |||
|
425 | (function () { | |||
|
426 | var _specialMacKeys = MochiKit.Signal._specialMacKeys; | |||
|
427 | for (i = 63236; i <= 63242; i++) { | |||
|
428 | // no F0 | |||
|
429 | _specialMacKeys[i] = 'KEY_F' + (i - 63236 + 1); | |||
|
430 | } | |||
|
431 | })(); | |||
|
432 | ||||
|
433 | /* Standard keyboard key codes. */ | |||
|
434 | MochiKit.Signal._specialKeys = { | |||
|
435 | 8: 'KEY_BACKSPACE', | |||
|
436 | 9: 'KEY_TAB', | |||
|
437 | 12: 'KEY_NUM_PAD_CLEAR', // weird, for Safari and Mac FF only | |||
|
438 | 13: 'KEY_ENTER', | |||
|
439 | 16: 'KEY_SHIFT', | |||
|
440 | 17: 'KEY_CTRL', | |||
|
441 | 18: 'KEY_ALT', | |||
|
442 | 19: 'KEY_PAUSE', | |||
|
443 | 20: 'KEY_CAPS_LOCK', | |||
|
444 | 27: 'KEY_ESCAPE', | |||
|
445 | 32: 'KEY_SPACEBAR', | |||
|
446 | 33: 'KEY_PAGE_UP', | |||
|
447 | 34: 'KEY_PAGE_DOWN', | |||
|
448 | 35: 'KEY_END', | |||
|
449 | 36: 'KEY_HOME', | |||
|
450 | 37: 'KEY_ARROW_LEFT', | |||
|
451 | 38: 'KEY_ARROW_UP', | |||
|
452 | 39: 'KEY_ARROW_RIGHT', | |||
|
453 | 40: 'KEY_ARROW_DOWN', | |||
|
454 | 44: 'KEY_PRINT_SCREEN', | |||
|
455 | 45: 'KEY_INSERT', | |||
|
456 | 46: 'KEY_DELETE', | |||
|
457 | 59: 'KEY_SEMICOLON', // weird, for Safari and IE only | |||
|
458 | 91: 'KEY_WINDOWS_LEFT', | |||
|
459 | 92: 'KEY_WINDOWS_RIGHT', | |||
|
460 | 93: 'KEY_SELECT', | |||
|
461 | 106: 'KEY_NUM_PAD_ASTERISK', | |||
|
462 | 107: 'KEY_NUM_PAD_PLUS_SIGN', | |||
|
463 | 109: 'KEY_NUM_PAD_HYPHEN-MINUS', | |||
|
464 | 110: 'KEY_NUM_PAD_FULL_STOP', | |||
|
465 | 111: 'KEY_NUM_PAD_SOLIDUS', | |||
|
466 | 144: 'KEY_NUM_LOCK', | |||
|
467 | 145: 'KEY_SCROLL_LOCK', | |||
|
468 | 186: 'KEY_SEMICOLON', | |||
|
469 | 187: 'KEY_EQUALS_SIGN', | |||
|
470 | 188: 'KEY_COMMA', | |||
|
471 | 189: 'KEY_HYPHEN-MINUS', | |||
|
472 | 190: 'KEY_FULL_STOP', | |||
|
473 | 191: 'KEY_SOLIDUS', | |||
|
474 | 192: 'KEY_GRAVE_ACCENT', | |||
|
475 | 219: 'KEY_LEFT_SQUARE_BRACKET', | |||
|
476 | 220: 'KEY_REVERSE_SOLIDUS', | |||
|
477 | 221: 'KEY_RIGHT_SQUARE_BRACKET', | |||
|
478 | 222: 'KEY_APOSTROPHE' | |||
|
479 | // undefined: 'KEY_UNKNOWN' | |||
|
480 | }; | |||
|
481 | ||||
|
482 | (function () { | |||
|
483 | /* for KEY_0 - KEY_9 */ | |||
|
484 | var _specialKeys = MochiKit.Signal._specialKeys; | |||
|
485 | for (var i = 48; i <= 57; i++) { | |||
|
486 | _specialKeys[i] = 'KEY_' + (i - 48); | |||
|
487 | } | |||
|
488 | ||||
|
489 | /* for KEY_A - KEY_Z */ | |||
|
490 | for (i = 65; i <= 90; i++) { | |||
|
491 | _specialKeys[i] = 'KEY_' + String.fromCharCode(i); | |||
|
492 | } | |||
|
493 | ||||
|
494 | /* for KEY_NUM_PAD_0 - KEY_NUM_PAD_9 */ | |||
|
495 | for (i = 96; i <= 105; i++) { | |||
|
496 | _specialKeys[i] = 'KEY_NUM_PAD_' + (i - 96); | |||
|
497 | } | |||
|
498 | ||||
|
499 | /* for KEY_F1 - KEY_F12 */ | |||
|
500 | for (i = 112; i <= 123; i++) { | |||
|
501 | // no F0 | |||
|
502 | _specialKeys[i] = 'KEY_F' + (i - 112 + 1); | |||
|
503 | } | |||
|
504 | })(); | |||
|
505 | ||||
|
506 | /* Internal object to keep track of created signals. */ | |||
|
507 | MochiKit.Signal.Ident = function (ident) { | |||
|
508 | this.source = ident.source; | |||
|
509 | this.signal = ident.signal; | |||
|
510 | this.listener = ident.listener; | |||
|
511 | this.isDOM = ident.isDOM; | |||
|
512 | this.objOrFunc = ident.objOrFunc; | |||
|
513 | this.funcOrStr = ident.funcOrStr; | |||
|
514 | this.connected = ident.connected; | |||
|
515 | }; | |||
|
516 | ||||
|
517 | MochiKit.Signal.Ident.prototype = {}; | |||
|
518 | ||||
|
519 | MochiKit.Base.update(MochiKit.Signal, { | |||
|
520 | ||||
|
521 | __repr__: function () { | |||
|
522 | return '[' + this.NAME + ' ' + this.VERSION + ']'; | |||
|
523 | }, | |||
|
524 | ||||
|
525 | toString: function () { | |||
|
526 | return this.__repr__(); | |||
|
527 | }, | |||
|
528 | ||||
|
529 | _unloadCache: function () { | |||
|
530 | var self = MochiKit.Signal; | |||
|
531 | var observers = self._observers; | |||
|
532 | ||||
|
533 | for (var i = 0; i < observers.length; i++) { | |||
|
534 | if (observers[i].signal !== 'onload' && observers[i].signal !== 'onunload') { | |||
|
535 | self._disconnect(observers[i]); | |||
|
536 | } | |||
|
537 | } | |||
|
538 | }, | |||
|
539 | ||||
|
540 | _listener: function (src, sig, func, obj, isDOM) { | |||
|
541 | var self = MochiKit.Signal; | |||
|
542 | var E = self.Event; | |||
|
543 | if (!isDOM) { | |||
|
544 | /* We don't want to re-bind already bound methods */ | |||
|
545 | if (typeof(func.im_self) == 'undefined') { | |||
|
546 | return MochiKit.Base.bind(func, obj); | |||
|
547 | } else { | |||
|
548 | return func; | |||
|
549 | } | |||
|
550 | } | |||
|
551 | obj = obj || src; | |||
|
552 | if (typeof(func) == "string") { | |||
|
553 | if (sig === 'onload' || sig === 'onunload') { | |||
|
554 | return function (nativeEvent) { | |||
|
555 | obj[func].apply(obj, [new E(src, nativeEvent)]); | |||
|
556 | ||||
|
557 | var ident = new MochiKit.Signal.Ident({ | |||
|
558 | source: src, signal: sig, objOrFunc: obj, funcOrStr: func}); | |||
|
559 | ||||
|
560 | MochiKit.Signal._disconnect(ident); | |||
|
561 | }; | |||
|
562 | } else { | |||
|
563 | return function (nativeEvent) { | |||
|
564 | obj[func].apply(obj, [new E(src, nativeEvent)]); | |||
|
565 | }; | |||
|
566 | } | |||
|
567 | } else { | |||
|
568 | if (sig === 'onload' || sig === 'onunload') { | |||
|
569 | return function (nativeEvent) { | |||
|
570 | func.apply(obj, [new E(src, nativeEvent)]); | |||
|
571 | ||||
|
572 | var ident = new MochiKit.Signal.Ident({ | |||
|
573 | source: src, signal: sig, objOrFunc: func}); | |||
|
574 | ||||
|
575 | MochiKit.Signal._disconnect(ident); | |||
|
576 | }; | |||
|
577 | } else { | |||
|
578 | return function (nativeEvent) { | |||
|
579 | func.apply(obj, [new E(src, nativeEvent)]); | |||
|
580 | }; | |||
|
581 | } | |||
|
582 | } | |||
|
583 | }, | |||
|
584 | ||||
|
585 | _browserAlreadyHasMouseEnterAndLeave: function () { | |||
|
586 | return /MSIE/.test(navigator.userAgent); | |||
|
587 | }, | |||
|
588 | ||||
|
589 | _mouseEnterListener: function (src, sig, func, obj) { | |||
|
590 | var E = MochiKit.Signal.Event; | |||
|
591 | return function (nativeEvent) { | |||
|
592 | var e = new E(src, nativeEvent); | |||
|
593 | try { | |||
|
594 | e.relatedTarget().nodeName; | |||
|
595 | } catch (err) { | |||
|
596 | /* probably hit a permission denied error; possibly one of | |||
|
597 | * firefox's screwy anonymous DIVs inside an input element. | |||
|
598 | * Allow this event to propogate up. | |||
|
599 | */ | |||
|
600 | return; | |||
|
601 | } | |||
|
602 | e.stop(); | |||
|
603 | if (MochiKit.DOM.isChildNode(e.relatedTarget(), src)) { | |||
|
604 | /* We've moved between our node and a child. Ignore. */ | |||
|
605 | return; | |||
|
606 | } | |||
|
607 | e.type = function () { return sig; }; | |||
|
608 | if (typeof(func) == "string") { | |||
|
609 | return obj[func].apply(obj, [e]); | |||
|
610 | } else { | |||
|
611 | return func.apply(obj, [e]); | |||
|
612 | } | |||
|
613 | }; | |||
|
614 | }, | |||
|
615 | ||||
|
616 | _getDestPair: function (objOrFunc, funcOrStr) { | |||
|
617 | var obj = null; | |||
|
618 | var func = null; | |||
|
619 | if (typeof(funcOrStr) != 'undefined') { | |||
|
620 | obj = objOrFunc; | |||
|
621 | func = funcOrStr; | |||
|
622 | if (typeof(funcOrStr) == 'string') { | |||
|
623 | if (typeof(objOrFunc[funcOrStr]) != "function") { | |||
|
624 | throw new Error("'funcOrStr' must be a function on 'objOrFunc'"); | |||
|
625 | } | |||
|
626 | } else if (typeof(funcOrStr) != 'function') { | |||
|
627 | throw new Error("'funcOrStr' must be a function or string"); | |||
|
628 | } | |||
|
629 | } else if (typeof(objOrFunc) != "function") { | |||
|
630 | throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given"); | |||
|
631 | } else { | |||
|
632 | func = objOrFunc; | |||
|
633 | } | |||
|
634 | return [obj, func]; | |||
|
635 | }, | |||
|
636 | ||||
|
637 | /** @id MochiKit.Signal.connect */ | |||
|
638 | connect: function (src, sig, objOrFunc/* optional */, funcOrStr) { | |||
|
639 | src = MochiKit.DOM.getElement(src); | |||
|
640 | var self = MochiKit.Signal; | |||
|
641 | ||||
|
642 | if (typeof(sig) != 'string') { | |||
|
643 | throw new Error("'sig' must be a string"); | |||
|
644 | } | |||
|
645 | ||||
|
646 | var destPair = self._getDestPair(objOrFunc, funcOrStr); | |||
|
647 | var obj = destPair[0]; | |||
|
648 | var func = destPair[1]; | |||
|
649 | if (typeof(obj) == 'undefined' || obj === null) { | |||
|
650 | obj = src; | |||
|
651 | } | |||
|
652 | ||||
|
653 | var isDOM = !!(src.addEventListener || src.attachEvent); | |||
|
654 | if (isDOM && (sig === "onmouseenter" || sig === "onmouseleave") | |||
|
655 | && !self._browserAlreadyHasMouseEnterAndLeave()) { | |||
|
656 | var listener = self._mouseEnterListener(src, sig.substr(2), func, obj); | |||
|
657 | if (sig === "onmouseenter") { | |||
|
658 | sig = "onmouseover"; | |||
|
659 | } else { | |||
|
660 | sig = "onmouseout"; | |||
|
661 | } | |||
|
662 | } else { | |||
|
663 | var listener = self._listener(src, sig, func, obj, isDOM); | |||
|
664 | } | |||
|
665 | ||||
|
666 | if (src.addEventListener) { | |||
|
667 | src.addEventListener(sig.substr(2), listener, false); | |||
|
668 | } else if (src.attachEvent) { | |||
|
669 | src.attachEvent(sig, listener); // useCapture unsupported | |||
|
670 | } | |||
|
671 | ||||
|
672 | var ident = new MochiKit.Signal.Ident({ | |||
|
673 | source: src, | |||
|
674 | signal: sig, | |||
|
675 | listener: listener, | |||
|
676 | isDOM: isDOM, | |||
|
677 | objOrFunc: objOrFunc, | |||
|
678 | funcOrStr: funcOrStr, | |||
|
679 | connected: true | |||
|
680 | }); | |||
|
681 | self._observers.push(ident); | |||
|
682 | ||||
|
683 | if (!isDOM && typeof(src.__connect__) == 'function') { | |||
|
684 | var args = MochiKit.Base.extend([ident], arguments, 1); | |||
|
685 | src.__connect__.apply(src, args); | |||
|
686 | } | |||
|
687 | ||||
|
688 | return ident; | |||
|
689 | }, | |||
|
690 | ||||
|
691 | _disconnect: function (ident) { | |||
|
692 | // already disconnected | |||
|
693 | if (!ident.connected) { | |||
|
694 | return; | |||
|
695 | } | |||
|
696 | ident.connected = false; | |||
|
697 | // check isDOM | |||
|
698 | if (!ident.isDOM) { | |||
|
699 | return; | |||
|
700 | } | |||
|
701 | var src = ident.source; | |||
|
702 | var sig = ident.signal; | |||
|
703 | var listener = ident.listener; | |||
|
704 | ||||
|
705 | if (src.removeEventListener) { | |||
|
706 | src.removeEventListener(sig.substr(2), listener, false); | |||
|
707 | } else if (src.detachEvent) { | |||
|
708 | src.detachEvent(sig, listener); // useCapture unsupported | |||
|
709 | } else { | |||
|
710 | throw new Error("'src' must be a DOM element"); | |||
|
711 | } | |||
|
712 | }, | |||
|
713 | ||||
|
714 | /** @id MochiKit.Signal.disconnect */ | |||
|
715 | disconnect: function (ident) { | |||
|
716 | var self = MochiKit.Signal; | |||
|
717 | var observers = self._observers; | |||
|
718 | var m = MochiKit.Base; | |||
|
719 | if (arguments.length > 1) { | |||
|
720 | // compatibility API | |||
|
721 | var src = MochiKit.DOM.getElement(arguments[0]); | |||
|
722 | var sig = arguments[1]; | |||
|
723 | var obj = arguments[2]; | |||
|
724 | var func = arguments[3]; | |||
|
725 | for (var i = observers.length - 1; i >= 0; i--) { | |||
|
726 | var o = observers[i]; | |||
|
727 | if (o.source === src && o.signal === sig && o.objOrFunc === obj && o.funcOrStr === func) { | |||
|
728 | self._disconnect(o); | |||
|
729 | if (!self._lock) { | |||
|
730 | observers.splice(i, 1); | |||
|
731 | } else { | |||
|
732 | self._dirty = true; | |||
|
733 | } | |||
|
734 | return true; | |||
|
735 | } | |||
|
736 | } | |||
|
737 | } else { | |||
|
738 | var idx = m.findIdentical(observers, ident); | |||
|
739 | if (idx >= 0) { | |||
|
740 | self._disconnect(ident); | |||
|
741 | if (!self._lock) { | |||
|
742 | observers.splice(idx, 1); | |||
|
743 | } else { | |||
|
744 | self._dirty = true; | |||
|
745 | } | |||
|
746 | return true; | |||
|
747 | } | |||
|
748 | } | |||
|
749 | return false; | |||
|
750 | }, | |||
|
751 | ||||
|
752 | /** @id MochiKit.Signal.disconnectAllTo */ | |||
|
753 | disconnectAllTo: function (objOrFunc, /* optional */funcOrStr) { | |||
|
754 | var self = MochiKit.Signal; | |||
|
755 | var observers = self._observers; | |||
|
756 | var disconnect = self._disconnect; | |||
|
757 | var locked = self._lock; | |||
|
758 | var dirty = self._dirty; | |||
|
759 | if (typeof(funcOrStr) === 'undefined') { | |||
|
760 | funcOrStr = null; | |||
|
761 | } | |||
|
762 | for (var i = observers.length - 1; i >= 0; i--) { | |||
|
763 | var ident = observers[i]; | |||
|
764 | if (ident.objOrFunc === objOrFunc && | |||
|
765 | (funcOrStr === null || ident.funcOrStr === funcOrStr)) { | |||
|
766 | disconnect(ident); | |||
|
767 | if (locked) { | |||
|
768 | dirty = true; | |||
|
769 | } else { | |||
|
770 | observers.splice(i, 1); | |||
|
771 | } | |||
|
772 | } | |||
|
773 | } | |||
|
774 | self._dirty = dirty; | |||
|
775 | }, | |||
|
776 | ||||
|
777 | /** @id MochiKit.Signal.disconnectAll */ | |||
|
778 | disconnectAll: function (src/* optional */, sig) { | |||
|
779 | src = MochiKit.DOM.getElement(src); | |||
|
780 | var m = MochiKit.Base; | |||
|
781 | var signals = m.flattenArguments(m.extend(null, arguments, 1)); | |||
|
782 | var self = MochiKit.Signal; | |||
|
783 | var disconnect = self._disconnect; | |||
|
784 | var observers = self._observers; | |||
|
785 | var i, ident; | |||
|
786 | var locked = self._lock; | |||
|
787 | var dirty = self._dirty; | |||
|
788 | if (signals.length === 0) { | |||
|
789 | // disconnect all | |||
|
790 | for (i = observers.length - 1; i >= 0; i--) { | |||
|
791 | ident = observers[i]; | |||
|
792 | if (ident.source === src) { | |||
|
793 | disconnect(ident); | |||
|
794 | if (!locked) { | |||
|
795 | observers.splice(i, 1); | |||
|
796 | } else { | |||
|
797 | dirty = true; | |||
|
798 | } | |||
|
799 | } | |||
|
800 | } | |||
|
801 | } else { | |||
|
802 | var sigs = {}; | |||
|
803 | for (i = 0; i < signals.length; i++) { | |||
|
804 | sigs[signals[i]] = true; | |||
|
805 | } | |||
|
806 | for (i = observers.length - 1; i >= 0; i--) { | |||
|
807 | ident = observers[i]; | |||
|
808 | if (ident.source === src && ident.signal in sigs) { | |||
|
809 | disconnect(ident); | |||
|
810 | if (!locked) { | |||
|
811 | observers.splice(i, 1); | |||
|
812 | } else { | |||
|
813 | dirty = true; | |||
|
814 | } | |||
|
815 | } | |||
|
816 | } | |||
|
817 | } | |||
|
818 | self._dirty = dirty; | |||
|
819 | }, | |||
|
820 | ||||
|
821 | /** @id MochiKit.Signal.signal */ | |||
|
822 | signal: function (src, sig) { | |||
|
823 | var self = MochiKit.Signal; | |||
|
824 | var observers = self._observers; | |||
|
825 | src = MochiKit.DOM.getElement(src); | |||
|
826 | var args = MochiKit.Base.extend(null, arguments, 2); | |||
|
827 | var errors = []; | |||
|
828 | self._lock = true; | |||
|
829 | for (var i = 0; i < observers.length; i++) { | |||
|
830 | var ident = observers[i]; | |||
|
831 | if (ident.source === src && ident.signal === sig && | |||
|
832 | ident.connected) { | |||
|
833 | try { | |||
|
834 | ident.listener.apply(src, args); | |||
|
835 | } catch (e) { | |||
|
836 | errors.push(e); | |||
|
837 | } | |||
|
838 | } | |||
|
839 | } | |||
|
840 | self._lock = false; | |||
|
841 | if (self._dirty) { | |||
|
842 | self._dirty = false; | |||
|
843 | for (var i = observers.length - 1; i >= 0; i--) { | |||
|
844 | if (!observers[i].connected) { | |||
|
845 | observers.splice(i, 1); | |||
|
846 | } | |||
|
847 | } | |||
|
848 | } | |||
|
849 | if (errors.length == 1) { | |||
|
850 | throw errors[0]; | |||
|
851 | } else if (errors.length > 1) { | |||
|
852 | var e = new Error("Multiple errors thrown in handling 'sig', see errors property"); | |||
|
853 | e.errors = errors; | |||
|
854 | throw e; | |||
|
855 | } | |||
|
856 | } | |||
|
857 | ||||
|
858 | }); | |||
|
859 | ||||
|
860 | MochiKit.Signal.EXPORT_OK = []; | |||
|
861 | ||||
|
862 | MochiKit.Signal.EXPORT = [ | |||
|
863 | 'connect', | |||
|
864 | 'disconnect', | |||
|
865 | 'signal', | |||
|
866 | 'disconnectAll', | |||
|
867 | 'disconnectAllTo' | |||
|
868 | ]; | |||
|
869 | ||||
|
870 | MochiKit.Signal.__new__ = function (win) { | |||
|
871 | var m = MochiKit.Base; | |||
|
872 | this._document = document; | |||
|
873 | this._window = win; | |||
|
874 | this._lock = false; | |||
|
875 | this._dirty = false; | |||
|
876 | ||||
|
877 | try { | |||
|
878 | this.connect(window, 'onunload', this._unloadCache); | |||
|
879 | } catch (e) { | |||
|
880 | // pass: might not be a browser | |||
|
881 | } | |||
|
882 | ||||
|
883 | this.EXPORT_TAGS = { | |||
|
884 | ':common': this.EXPORT, | |||
|
885 | ':all': m.concat(this.EXPORT, this.EXPORT_OK) | |||
|
886 | }; | |||
|
887 | ||||
|
888 | m.nameFunctions(this); | |||
|
889 | }; | |||
|
890 | ||||
|
891 | MochiKit.Signal.__new__(this); | |||
|
892 | ||||
|
893 | // | |||
|
894 | // XXX: Internet Explorer blows | |||
|
895 | // | |||
|
896 | if (MochiKit.__export__) { | |||
|
897 | connect = MochiKit.Signal.connect; | |||
|
898 | disconnect = MochiKit.Signal.disconnect; | |||
|
899 | disconnectAll = MochiKit.Signal.disconnectAll; | |||
|
900 | signal = MochiKit.Signal.signal; | |||
|
901 | } | |||
|
902 | ||||
|
903 | MochiKit.Base._exportSymbols(this, MochiKit.Signal); |
This diff has been collapsed as it changes many lines, (589 lines changed) Show them Hide them | |||||
@@ -0,0 +1,589 b'' | |||||
|
1 | /*** | |||
|
2 | Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) | |||
|
3 | Mochi-ized By Thomas Herve (_firstname_@nimail.org) | |||
|
4 | ||||
|
5 | See scriptaculous.js for full license. | |||
|
6 | ||||
|
7 | ***/ | |||
|
8 | ||||
|
9 | if (typeof(dojo) != 'undefined') { | |||
|
10 | dojo.provide('MochiKit.Sortable'); | |||
|
11 | dojo.require('MochiKit.Base'); | |||
|
12 | dojo.require('MochiKit.DOM'); | |||
|
13 | dojo.require('MochiKit.Iter'); | |||
|
14 | } | |||
|
15 | ||||
|
16 | if (typeof(JSAN) != 'undefined') { | |||
|
17 | JSAN.use("MochiKit.Base", []); | |||
|
18 | JSAN.use("MochiKit.DOM", []); | |||
|
19 | JSAN.use("MochiKit.Iter", []); | |||
|
20 | } | |||
|
21 | ||||
|
22 | try { | |||
|
23 | if (typeof(MochiKit.Base) == 'undefined' || | |||
|
24 | typeof(MochiKit.DOM) == 'undefined' || | |||
|
25 | typeof(MochiKit.Iter) == 'undefined') { | |||
|
26 | throw ""; | |||
|
27 | } | |||
|
28 | } catch (e) { | |||
|
29 | throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM and MochiKit.Iter!"; | |||
|
30 | } | |||
|
31 | ||||
|
32 | if (typeof(MochiKit.Sortable) == 'undefined') { | |||
|
33 | MochiKit.Sortable = {}; | |||
|
34 | } | |||
|
35 | ||||
|
36 | MochiKit.Sortable.NAME = 'MochiKit.Sortable'; | |||
|
37 | MochiKit.Sortable.VERSION = '1.4'; | |||
|
38 | ||||
|
39 | MochiKit.Sortable.__repr__ = function () { | |||
|
40 | return '[' + this.NAME + ' ' + this.VERSION + ']'; | |||
|
41 | }; | |||
|
42 | ||||
|
43 | MochiKit.Sortable.toString = function () { | |||
|
44 | return this.__repr__(); | |||
|
45 | }; | |||
|
46 | ||||
|
47 | MochiKit.Sortable.EXPORT = [ | |||
|
48 | ]; | |||
|
49 | ||||
|
50 | MochiKit.Sortable.EXPORT_OK = [ | |||
|
51 | ]; | |||
|
52 | ||||
|
53 | MochiKit.Base.update(MochiKit.Sortable, { | |||
|
54 | /*** | |||
|
55 | ||||
|
56 | Manage sortables. Mainly use the create function to add a sortable. | |||
|
57 | ||||
|
58 | ***/ | |||
|
59 | sortables: {}, | |||
|
60 | ||||
|
61 | _findRootElement: function (element) { | |||
|
62 | while (element.tagName.toUpperCase() != "BODY") { | |||
|
63 | if (element.id && MochiKit.Sortable.sortables[element.id]) { | |||
|
64 | return element; | |||
|
65 | } | |||
|
66 | element = element.parentNode; | |||
|
67 | } | |||
|
68 | }, | |||
|
69 | ||||
|
70 | /** @id MochiKit.Sortable.options */ | |||
|
71 | options: function (element) { | |||
|
72 | element = MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(element)); | |||
|
73 | if (!element) { | |||
|
74 | return; | |||
|
75 | } | |||
|
76 | return MochiKit.Sortable.sortables[element.id]; | |||
|
77 | }, | |||
|
78 | ||||
|
79 | /** @id MochiKit.Sortable.destroy */ | |||
|
80 | destroy: function (element){ | |||
|
81 | var s = MochiKit.Sortable.options(element); | |||
|
82 | var b = MochiKit.Base; | |||
|
83 | var d = MochiKit.DragAndDrop; | |||
|
84 | ||||
|
85 | if (s) { | |||
|
86 | MochiKit.Signal.disconnect(s.startHandle); | |||
|
87 | MochiKit.Signal.disconnect(s.endHandle); | |||
|
88 | b.map(function (dr) { | |||
|
89 | d.Droppables.remove(dr); | |||
|
90 | }, s.droppables); | |||
|
91 | b.map(function (dr) { | |||
|
92 | dr.destroy(); | |||
|
93 | }, s.draggables); | |||
|
94 | ||||
|
95 | delete MochiKit.Sortable.sortables[s.element.id]; | |||
|
96 | } | |||
|
97 | }, | |||
|
98 | ||||
|
99 | /** @id MochiKit.Sortable.create */ | |||
|
100 | create: function (element, options) { | |||
|
101 | element = MochiKit.DOM.getElement(element); | |||
|
102 | var self = MochiKit.Sortable; | |||
|
103 | ||||
|
104 | /** @id MochiKit.Sortable.options */ | |||
|
105 | options = MochiKit.Base.update({ | |||
|
106 | ||||
|
107 | /** @id MochiKit.Sortable.element */ | |||
|
108 | element: element, | |||
|
109 | ||||
|
110 | /** @id MochiKit.Sortable.tag */ | |||
|
111 | tag: 'li', // assumes li children, override with tag: 'tagname' | |||
|
112 | ||||
|
113 | /** @id MochiKit.Sortable.dropOnEmpty */ | |||
|
114 | dropOnEmpty: false, | |||
|
115 | ||||
|
116 | /** @id MochiKit.Sortable.tree */ | |||
|
117 | tree: false, | |||
|
118 | ||||
|
119 | /** @id MochiKit.Sortable.treeTag */ | |||
|
120 | treeTag: 'ul', | |||
|
121 | ||||
|
122 | /** @id MochiKit.Sortable.overlap */ | |||
|
123 | overlap: 'vertical', // one of 'vertical', 'horizontal' | |||
|
124 | ||||
|
125 | /** @id MochiKit.Sortable.constraint */ | |||
|
126 | constraint: 'vertical', // one of 'vertical', 'horizontal', false | |||
|
127 | // also takes array of elements (or ids); or false | |||
|
128 | ||||
|
129 | /** @id MochiKit.Sortable.containment */ | |||
|
130 | containment: [element], | |||
|
131 | ||||
|
132 | /** @id MochiKit.Sortable.handle */ | |||
|
133 | handle: false, // or a CSS class | |||
|
134 | ||||
|
135 | /** @id MochiKit.Sortable.only */ | |||
|
136 | only: false, | |||
|
137 | ||||
|
138 | /** @id MochiKit.Sortable.hoverclass */ | |||
|
139 | hoverclass: null, | |||
|
140 | ||||
|
141 | /** @id MochiKit.Sortable.ghosting */ | |||
|
142 | ghosting: false, | |||
|
143 | ||||
|
144 | /** @id MochiKit.Sortable.scroll */ | |||
|
145 | scroll: false, | |||
|
146 | ||||
|
147 | /** @id MochiKit.Sortable.scrollSensitivity */ | |||
|
148 | scrollSensitivity: 20, | |||
|
149 | ||||
|
150 | /** @id MochiKit.Sortable.scrollSpeed */ | |||
|
151 | scrollSpeed: 15, | |||
|
152 | ||||
|
153 | /** @id MochiKit.Sortable.format */ | |||
|
154 | format: /^[^_]*_(.*)$/, | |||
|
155 | ||||
|
156 | /** @id MochiKit.Sortable.onChange */ | |||
|
157 | onChange: MochiKit.Base.noop, | |||
|
158 | ||||
|
159 | /** @id MochiKit.Sortable.onUpdate */ | |||
|
160 | onUpdate: MochiKit.Base.noop, | |||
|
161 | ||||
|
162 | /** @id MochiKit.Sortable.accept */ | |||
|
163 | accept: null | |||
|
164 | }, options); | |||
|
165 | ||||
|
166 | // clear any old sortable with same element | |||
|
167 | self.destroy(element); | |||
|
168 | ||||
|
169 | // build options for the draggables | |||
|
170 | var options_for_draggable = { | |||
|
171 | revert: true, | |||
|
172 | ghosting: options.ghosting, | |||
|
173 | scroll: options.scroll, | |||
|
174 | scrollSensitivity: options.scrollSensitivity, | |||
|
175 | scrollSpeed: options.scrollSpeed, | |||
|
176 | constraint: options.constraint, | |||
|
177 | handle: options.handle | |||
|
178 | }; | |||
|
179 | ||||
|
180 | if (options.starteffect) { | |||
|
181 | options_for_draggable.starteffect = options.starteffect; | |||
|
182 | } | |||
|
183 | ||||
|
184 | if (options.reverteffect) { | |||
|
185 | options_for_draggable.reverteffect = options.reverteffect; | |||
|
186 | } else if (options.ghosting) { | |||
|
187 | options_for_draggable.reverteffect = function (innerelement) { | |||
|
188 | innerelement.style.top = 0; | |||
|
189 | innerelement.style.left = 0; | |||
|
190 | }; | |||
|
191 | } | |||
|
192 | ||||
|
193 | if (options.endeffect) { | |||
|
194 | options_for_draggable.endeffect = options.endeffect; | |||
|
195 | } | |||
|
196 | ||||
|
197 | if (options.zindex) { | |||
|
198 | options_for_draggable.zindex = options.zindex; | |||
|
199 | } | |||
|
200 | ||||
|
201 | // build options for the droppables | |||
|
202 | var options_for_droppable = { | |||
|
203 | overlap: options.overlap, | |||
|
204 | containment: options.containment, | |||
|
205 | hoverclass: options.hoverclass, | |||
|
206 | onhover: self.onHover, | |||
|
207 | tree: options.tree, | |||
|
208 | accept: options.accept | |||
|
209 | } | |||
|
210 | ||||
|
211 | var options_for_tree = { | |||
|
212 | onhover: self.onEmptyHover, | |||
|
213 | overlap: options.overlap, | |||
|
214 | containment: options.containment, | |||
|
215 | hoverclass: options.hoverclass, | |||
|
216 | accept: options.accept | |||
|
217 | } | |||
|
218 | ||||
|
219 | // fix for gecko engine | |||
|
220 | MochiKit.DOM.removeEmptyTextNodes(element); | |||
|
221 | ||||
|
222 | options.draggables = []; | |||
|
223 | options.droppables = []; | |||
|
224 | ||||
|
225 | // drop on empty handling | |||
|
226 | if (options.dropOnEmpty || options.tree) { | |||
|
227 | new MochiKit.DragAndDrop.Droppable(element, options_for_tree); | |||
|
228 | options.droppables.push(element); | |||
|
229 | } | |||
|
230 | MochiKit.Base.map(function (e) { | |||
|
231 | // handles are per-draggable | |||
|
232 | var handle = options.handle ? | |||
|
233 | MochiKit.DOM.getFirstElementByTagAndClassName(null, | |||
|
234 | options.handle, e) : e; | |||
|
235 | options.draggables.push( | |||
|
236 | new MochiKit.DragAndDrop.Draggable(e, | |||
|
237 | MochiKit.Base.update(options_for_draggable, | |||
|
238 | {handle: handle}))); | |||
|
239 | new MochiKit.DragAndDrop.Droppable(e, options_for_droppable); | |||
|
240 | if (options.tree) { | |||
|
241 | e.treeNode = element; | |||
|
242 | } | |||
|
243 | options.droppables.push(e); | |||
|
244 | }, (self.findElements(element, options) || [])); | |||
|
245 | ||||
|
246 | if (options.tree) { | |||
|
247 | MochiKit.Base.map(function (e) { | |||
|
248 | new MochiKit.DragAndDrop.Droppable(e, options_for_tree); | |||
|
249 | e.treeNode = element; | |||
|
250 | options.droppables.push(e); | |||
|
251 | }, (self.findTreeElements(element, options) || [])); | |||
|
252 | } | |||
|
253 | ||||
|
254 | // keep reference | |||
|
255 | self.sortables[element.id] = options; | |||
|
256 | ||||
|
257 | options.lastValue = self.serialize(element); | |||
|
258 | options.startHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'start', | |||
|
259 | MochiKit.Base.partial(self.onStart, element)); | |||
|
260 | options.endHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end', | |||
|
261 | MochiKit.Base.partial(self.onEnd, element)); | |||
|
262 | }, | |||
|
263 | ||||
|
264 | /** @id MochiKit.Sortable.onStart */ | |||
|
265 | onStart: function (element, draggable) { | |||
|
266 | var self = MochiKit.Sortable; | |||
|
267 | var options = self.options(element); | |||
|
268 | options.lastValue = self.serialize(options.element); | |||
|
269 | }, | |||
|
270 | ||||
|
271 | /** @id MochiKit.Sortable.onEnd */ | |||
|
272 | onEnd: function (element, draggable) { | |||
|
273 | var self = MochiKit.Sortable; | |||
|
274 | self.unmark(); | |||
|
275 | var options = self.options(element); | |||
|
276 | if (options.lastValue != self.serialize(options.element)) { | |||
|
277 | options.onUpdate(options.element); | |||
|
278 | } | |||
|
279 | }, | |||
|
280 | ||||
|
281 | // return all suitable-for-sortable elements in a guaranteed order | |||
|
282 | ||||
|
283 | /** @id MochiKit.Sortable.findElements */ | |||
|
284 | findElements: function (element, options) { | |||
|
285 | return MochiKit.Sortable.findChildren( | |||
|
286 | element, options.only, options.tree ? true : false, options.tag); | |||
|
287 | }, | |||
|
288 | ||||
|
289 | /** @id MochiKit.Sortable.findTreeElements */ | |||
|
290 | findTreeElements: function (element, options) { | |||
|
291 | return MochiKit.Sortable.findChildren( | |||
|
292 | element, options.only, options.tree ? true : false, options.treeTag); | |||
|
293 | }, | |||
|
294 | ||||
|
295 | /** @id MochiKit.Sortable.findChildren */ | |||
|
296 | findChildren: function (element, only, recursive, tagName) { | |||
|
297 | if (!element.hasChildNodes()) { | |||
|
298 | return null; | |||
|
299 | } | |||
|
300 | tagName = tagName.toUpperCase(); | |||
|
301 | if (only) { | |||
|
302 | only = MochiKit.Base.flattenArray([only]); | |||
|
303 | } | |||
|
304 | var elements = []; | |||
|
305 | MochiKit.Base.map(function (e) { | |||
|
306 | if (e.tagName && | |||
|
307 | e.tagName.toUpperCase() == tagName && | |||
|
308 | (!only || | |||
|
309 | MochiKit.Iter.some(only, function (c) { | |||
|
310 | return MochiKit.DOM.hasElementClass(e, c); | |||
|
311 | }))) { | |||
|
312 | elements.push(e); | |||
|
313 | } | |||
|
314 | if (recursive) { | |||
|
315 | var grandchildren = MochiKit.Sortable.findChildren(e, only, recursive, tagName); | |||
|
316 | if (grandchildren && grandchildren.length > 0) { | |||
|
317 | elements = elements.concat(grandchildren); | |||
|
318 | } | |||
|
319 | } | |||
|
320 | }, element.childNodes); | |||
|
321 | return elements; | |||
|
322 | }, | |||
|
323 | ||||
|
324 | /** @id MochiKit.Sortable.onHover */ | |||
|
325 | onHover: function (element, dropon, overlap) { | |||
|
326 | if (MochiKit.DOM.isParent(dropon, element)) { | |||
|
327 | return; | |||
|
328 | } | |||
|
329 | var self = MochiKit.Sortable; | |||
|
330 | ||||
|
331 | if (overlap > .33 && overlap < .66 && self.options(dropon).tree) { | |||
|
332 | return; | |||
|
333 | } else if (overlap > 0.5) { | |||
|
334 | self.mark(dropon, 'before'); | |||
|
335 | if (dropon.previousSibling != element) { | |||
|
336 | var oldParentNode = element.parentNode; | |||
|
337 | element.style.visibility = 'hidden'; // fix gecko rendering | |||
|
338 | dropon.parentNode.insertBefore(element, dropon); | |||
|
339 | if (dropon.parentNode != oldParentNode) { | |||
|
340 | self.options(oldParentNode).onChange(element); | |||
|
341 | } | |||
|
342 | self.options(dropon.parentNode).onChange(element); | |||
|
343 | } | |||
|
344 | } else { | |||
|
345 | self.mark(dropon, 'after'); | |||
|
346 | var nextElement = dropon.nextSibling || null; | |||
|
347 | if (nextElement != element) { | |||
|
348 | var oldParentNode = element.parentNode; | |||
|
349 | element.style.visibility = 'hidden'; // fix gecko rendering | |||
|
350 | dropon.parentNode.insertBefore(element, nextElement); | |||
|
351 | if (dropon.parentNode != oldParentNode) { | |||
|
352 | self.options(oldParentNode).onChange(element); | |||
|
353 | } | |||
|
354 | self.options(dropon.parentNode).onChange(element); | |||
|
355 | } | |||
|
356 | } | |||
|
357 | }, | |||
|
358 | ||||
|
359 | _offsetSize: function (element, type) { | |||
|
360 | if (type == 'vertical' || type == 'height') { | |||
|
361 | return element.offsetHeight; | |||
|
362 | } else { | |||
|
363 | return element.offsetWidth; | |||
|
364 | } | |||
|
365 | }, | |||
|
366 | ||||
|
367 | /** @id MochiKit.Sortable.onEmptyHover */ | |||
|
368 | onEmptyHover: function (element, dropon, overlap) { | |||
|
369 | var oldParentNode = element.parentNode; | |||
|
370 | var self = MochiKit.Sortable; | |||
|
371 | var droponOptions = self.options(dropon); | |||
|
372 | ||||
|
373 | if (!MochiKit.DOM.isParent(dropon, element)) { | |||
|
374 | var index; | |||
|
375 | ||||
|
376 | var children = self.findElements(dropon, {tag: droponOptions.tag, | |||
|
377 | only: droponOptions.only}); | |||
|
378 | var child = null; | |||
|
379 | ||||
|
380 | if (children) { | |||
|
381 | var offset = self._offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); | |||
|
382 | ||||
|
383 | for (index = 0; index < children.length; index += 1) { | |||
|
384 | if (offset - self._offsetSize(children[index], droponOptions.overlap) >= 0) { | |||
|
385 | offset -= self._offsetSize(children[index], droponOptions.overlap); | |||
|
386 | } else if (offset - (self._offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { | |||
|
387 | child = index + 1 < children.length ? children[index + 1] : null; | |||
|
388 | break; | |||
|
389 | } else { | |||
|
390 | child = children[index]; | |||
|
391 | break; | |||
|
392 | } | |||
|
393 | } | |||
|
394 | } | |||
|
395 | ||||
|
396 | dropon.insertBefore(element, child); | |||
|
397 | ||||
|
398 | self.options(oldParentNode).onChange(element); | |||
|
399 | droponOptions.onChange(element); | |||
|
400 | } | |||
|
401 | }, | |||
|
402 | ||||
|
403 | /** @id MochiKit.Sortable.unmark */ | |||
|
404 | unmark: function () { | |||
|
405 | var m = MochiKit.Sortable._marker; | |||
|
406 | if (m) { | |||
|
407 | MochiKit.Style.hideElement(m); | |||
|
408 | } | |||
|
409 | }, | |||
|
410 | ||||
|
411 | /** @id MochiKit.Sortable.mark */ | |||
|
412 | mark: function (dropon, position) { | |||
|
413 | // mark on ghosting only | |||
|
414 | var d = MochiKit.DOM; | |||
|
415 | var self = MochiKit.Sortable; | |||
|
416 | var sortable = self.options(dropon.parentNode); | |||
|
417 | if (sortable && !sortable.ghosting) { | |||
|
418 | return; | |||
|
419 | } | |||
|
420 | ||||
|
421 | if (!self._marker) { | |||
|
422 | self._marker = d.getElement('dropmarker') || | |||
|
423 | document.createElement('DIV'); | |||
|
424 | MochiKit.Style.hideElement(self._marker); | |||
|
425 | d.addElementClass(self._marker, 'dropmarker'); | |||
|
426 | self._marker.style.position = 'absolute'; | |||
|
427 | document.getElementsByTagName('body').item(0).appendChild(self._marker); | |||
|
428 | } | |||
|
429 | var offsets = MochiKit.Position.cumulativeOffset(dropon); | |||
|
430 | self._marker.style.left = offsets.x + 'px'; | |||
|
431 | self._marker.style.top = offsets.y + 'px'; | |||
|
432 | ||||
|
433 | if (position == 'after') { | |||
|
434 | if (sortable.overlap == 'horizontal') { | |||
|
435 | self._marker.style.left = (offsets.x + dropon.clientWidth) + 'px'; | |||
|
436 | } else { | |||
|
437 | self._marker.style.top = (offsets.y + dropon.clientHeight) + 'px'; | |||
|
438 | } | |||
|
439 | } | |||
|
440 | MochiKit.Style.showElement(self._marker); | |||
|
441 | }, | |||
|
442 | ||||
|
443 | _tree: function (element, options, parent) { | |||
|
444 | var self = MochiKit.Sortable; | |||
|
445 | var children = self.findElements(element, options) || []; | |||
|
446 | ||||
|
447 | for (var i = 0; i < children.length; ++i) { | |||
|
448 | var match = children[i].id.match(options.format); | |||
|
449 | ||||
|
450 | if (!match) { | |||
|
451 | continue; | |||
|
452 | } | |||
|
453 | ||||
|
454 | var child = { | |||
|
455 | id: encodeURIComponent(match ? match[1] : null), | |||
|
456 | element: element, | |||
|
457 | parent: parent, | |||
|
458 | children: [], | |||
|
459 | position: parent.children.length, | |||
|
460 | container: self._findChildrenElement(children[i], options.treeTag.toUpperCase()) | |||
|
461 | } | |||
|
462 | ||||
|
463 | /* Get the element containing the children and recurse over it */ | |||
|
464 | if (child.container) { | |||
|
465 | self._tree(child.container, options, child) | |||
|
466 | } | |||
|
467 | ||||
|
468 | parent.children.push (child); | |||
|
469 | } | |||
|
470 | ||||
|
471 | return parent; | |||
|
472 | }, | |||
|
473 | ||||
|
474 | /* Finds the first element of the given tag type within a parent element. | |||
|
475 | Used for finding the first LI[ST] within a L[IST]I[TEM].*/ | |||
|
476 | _findChildrenElement: function (element, containerTag) { | |||
|
477 | if (element && element.hasChildNodes) { | |||
|
478 | containerTag = containerTag.toUpperCase(); | |||
|
479 | for (var i = 0; i < element.childNodes.length; ++i) { | |||
|
480 | if (element.childNodes[i].tagName.toUpperCase() == containerTag) { | |||
|
481 | return element.childNodes[i]; | |||
|
482 | } | |||
|
483 | } | |||
|
484 | } | |||
|
485 | return null; | |||
|
486 | }, | |||
|
487 | ||||
|
488 | /** @id MochiKit.Sortable.tree */ | |||
|
489 | tree: function (element, options) { | |||
|
490 | element = MochiKit.DOM.getElement(element); | |||
|
491 | var sortableOptions = MochiKit.Sortable.options(element); | |||
|
492 | options = MochiKit.Base.update({ | |||
|
493 | tag: sortableOptions.tag, | |||
|
494 | treeTag: sortableOptions.treeTag, | |||
|
495 | only: sortableOptions.only, | |||
|
496 | name: element.id, | |||
|
497 | format: sortableOptions.format | |||
|
498 | }, options || {}); | |||
|
499 | ||||
|
500 | var root = { | |||
|
501 | id: null, | |||
|
502 | parent: null, | |||
|
503 | children: new Array, | |||
|
504 | container: element, | |||
|
505 | position: 0 | |||
|
506 | } | |||
|
507 | ||||
|
508 | return MochiKit.Sortable._tree(element, options, root); | |||
|
509 | }, | |||
|
510 | ||||
|
511 | /** | |||
|
512 | * Specifies the sequence for the Sortable. | |||
|
513 | * @param {Node} element Element to use as the Sortable. | |||
|
514 | * @param {Object} newSequence New sequence to use. | |||
|
515 | * @param {Object} options Options to use fro the Sortable. | |||
|
516 | */ | |||
|
517 | setSequence: function (element, newSequence, options) { | |||
|
518 | var self = MochiKit.Sortable; | |||
|
519 | var b = MochiKit.Base; | |||
|
520 | element = MochiKit.DOM.getElement(element); | |||
|
521 | options = b.update(self.options(element), options || {}); | |||
|
522 | ||||
|
523 | var nodeMap = {}; | |||
|
524 | b.map(function (n) { | |||
|
525 | var m = n.id.match(options.format); | |||
|
526 | if (m) { | |||
|
527 | nodeMap[m[1]] = [n, n.parentNode]; | |||
|
528 | } | |||
|
529 | n.parentNode.removeChild(n); | |||
|
530 | }, self.findElements(element, options)); | |||
|
531 | ||||
|
532 | b.map(function (ident) { | |||
|
533 | var n = nodeMap[ident]; | |||
|
534 | if (n) { | |||
|
535 | n[1].appendChild(n[0]); | |||
|
536 | delete nodeMap[ident]; | |||
|
537 | } | |||
|
538 | }, newSequence); | |||
|
539 | }, | |||
|
540 | ||||
|
541 | /* Construct a [i] index for a particular node */ | |||
|
542 | _constructIndex: function (node) { | |||
|
543 | var index = ''; | |||
|
544 | do { | |||
|
545 | if (node.id) { | |||
|
546 | index = '[' + node.position + ']' + index; | |||
|
547 | } | |||
|
548 | } while ((node = node.parent) != null); | |||
|
549 | return index; | |||
|
550 | }, | |||
|
551 | ||||
|
552 | /** @id MochiKit.Sortable.sequence */ | |||
|
553 | sequence: function (element, options) { | |||
|
554 | element = MochiKit.DOM.getElement(element); | |||
|
555 | var self = MochiKit.Sortable; | |||
|
556 | var options = MochiKit.Base.update(self.options(element), options || {}); | |||
|
557 | ||||
|
558 | return MochiKit.Base.map(function (item) { | |||
|
559 | return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; | |||
|
560 | }, MochiKit.DOM.getElement(self.findElements(element, options) || [])); | |||
|
561 | }, | |||
|
562 | ||||
|
563 | /** | |||
|
564 | * Serializes the content of a Sortable. Useful to send this content through a XMLHTTPRequest. | |||
|
565 | * These options override the Sortable options for the serialization only. | |||
|
566 | * @param {Node} element Element to serialize. | |||
|
567 | * @param {Object} options Serialization options. | |||
|
568 | */ | |||
|
569 | serialize: function (element, options) { | |||
|
570 | element = MochiKit.DOM.getElement(element); | |||
|
571 | var self = MochiKit.Sortable; | |||
|
572 | options = MochiKit.Base.update(self.options(element), options || {}); | |||
|
573 | var name = encodeURIComponent(options.name || element.id); | |||
|
574 | ||||
|
575 | if (options.tree) { | |||
|
576 | return MochiKit.Base.flattenArray(MochiKit.Base.map(function (item) { | |||
|
577 | return [name + self._constructIndex(item) + "[id]=" + | |||
|
578 | encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); | |||
|
579 | }, self.tree(element, options).children)).join('&'); | |||
|
580 | } else { | |||
|
581 | return MochiKit.Base.map(function (item) { | |||
|
582 | return name + "[]=" + encodeURIComponent(item); | |||
|
583 | }, self.sequence(element, options)).join('&'); | |||
|
584 | } | |||
|
585 | } | |||
|
586 | }); | |||
|
587 | ||||
|
588 | // trunk compatibility | |||
|
589 | MochiKit.Sortable.Sortable = MochiKit.Sortable; |
@@ -0,0 +1,445 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.Style 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005-2006 Bob Ippolito, Beau Hartshorne. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.Style'); | |||
|
13 | dojo.require('MochiKit.Base'); | |||
|
14 | dojo.require('MochiKit.DOM'); | |||
|
15 | } | |||
|
16 | if (typeof(JSAN) != 'undefined') { | |||
|
17 | JSAN.use('MochiKit.Base', []); | |||
|
18 | JSAN.use('MochiKit.DOM', []); | |||
|
19 | } | |||
|
20 | ||||
|
21 | try { | |||
|
22 | if (typeof(MochiKit.Base) == 'undefined') { | |||
|
23 | throw ''; | |||
|
24 | } | |||
|
25 | } catch (e) { | |||
|
26 | throw 'MochiKit.Style depends on MochiKit.Base!'; | |||
|
27 | } | |||
|
28 | ||||
|
29 | try { | |||
|
30 | if (typeof(MochiKit.DOM) == 'undefined') { | |||
|
31 | throw ''; | |||
|
32 | } | |||
|
33 | } catch (e) { | |||
|
34 | throw 'MochiKit.Style depends on MochiKit.DOM!'; | |||
|
35 | } | |||
|
36 | ||||
|
37 | ||||
|
38 | if (typeof(MochiKit.Style) == 'undefined') { | |||
|
39 | MochiKit.Style = {}; | |||
|
40 | } | |||
|
41 | ||||
|
42 | MochiKit.Style.NAME = 'MochiKit.Style'; | |||
|
43 | MochiKit.Style.VERSION = '1.4'; | |||
|
44 | MochiKit.Style.__repr__ = function () { | |||
|
45 | return '[' + this.NAME + ' ' + this.VERSION + ']'; | |||
|
46 | }; | |||
|
47 | MochiKit.Style.toString = function () { | |||
|
48 | return this.__repr__(); | |||
|
49 | }; | |||
|
50 | ||||
|
51 | MochiKit.Style.EXPORT_OK = []; | |||
|
52 | ||||
|
53 | MochiKit.Style.EXPORT = [ | |||
|
54 | 'setStyle', | |||
|
55 | 'setOpacity', | |||
|
56 | 'getStyle', | |||
|
57 | 'getElementDimensions', | |||
|
58 | 'elementDimensions', // deprecated | |||
|
59 | 'setElementDimensions', | |||
|
60 | 'getElementPosition', | |||
|
61 | 'elementPosition', // deprecated | |||
|
62 | 'setElementPosition', | |||
|
63 | 'setDisplayForElement', | |||
|
64 | 'hideElement', | |||
|
65 | 'showElement', | |||
|
66 | 'getViewportDimensions', | |||
|
67 | 'getViewportPosition', | |||
|
68 | 'Dimensions', | |||
|
69 | 'Coordinates' | |||
|
70 | ]; | |||
|
71 | ||||
|
72 | ||||
|
73 | /* | |||
|
74 | ||||
|
75 | Dimensions | |||
|
76 | ||||
|
77 | */ | |||
|
78 | /** @id MochiKit.Style.Dimensions */ | |||
|
79 | MochiKit.Style.Dimensions = function (w, h) { | |||
|
80 | this.w = w; | |||
|
81 | this.h = h; | |||
|
82 | }; | |||
|
83 | ||||
|
84 | MochiKit.Style.Dimensions.prototype.__repr__ = function () { | |||
|
85 | var repr = MochiKit.Base.repr; | |||
|
86 | return '{w: ' + repr(this.w) + ', h: ' + repr(this.h) + '}'; | |||
|
87 | }; | |||
|
88 | ||||
|
89 | MochiKit.Style.Dimensions.prototype.toString = function () { | |||
|
90 | return this.__repr__(); | |||
|
91 | }; | |||
|
92 | ||||
|
93 | ||||
|
94 | /* | |||
|
95 | ||||
|
96 | Coordinates | |||
|
97 | ||||
|
98 | */ | |||
|
99 | /** @id MochiKit.Style.Coordinates */ | |||
|
100 | MochiKit.Style.Coordinates = function (x, y) { | |||
|
101 | this.x = x; | |||
|
102 | this.y = y; | |||
|
103 | }; | |||
|
104 | ||||
|
105 | MochiKit.Style.Coordinates.prototype.__repr__ = function () { | |||
|
106 | var repr = MochiKit.Base.repr; | |||
|
107 | return '{x: ' + repr(this.x) + ', y: ' + repr(this.y) + '}'; | |||
|
108 | }; | |||
|
109 | ||||
|
110 | MochiKit.Style.Coordinates.prototype.toString = function () { | |||
|
111 | return this.__repr__(); | |||
|
112 | }; | |||
|
113 | ||||
|
114 | ||||
|
115 | MochiKit.Base.update(MochiKit.Style, { | |||
|
116 | ||||
|
117 | /** @id MochiKit.Style.getStyle */ | |||
|
118 | getStyle: function (elem, cssProperty) { | |||
|
119 | var dom = MochiKit.DOM; | |||
|
120 | var d = dom._document; | |||
|
121 | ||||
|
122 | elem = dom.getElement(elem); | |||
|
123 | cssProperty = MochiKit.Base.camelize(cssProperty); | |||
|
124 | ||||
|
125 | if (!elem || elem == d) { | |||
|
126 | return undefined; | |||
|
127 | } | |||
|
128 | if (cssProperty == 'opacity' && elem.filters) { | |||
|
129 | var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/); | |||
|
130 | if (opacity && opacity[1]) { | |||
|
131 | return parseFloat(opacity[1]) / 100; | |||
|
132 | } | |||
|
133 | return 1.0; | |||
|
134 | } | |||
|
135 | var value = elem.style ? elem.style[cssProperty] : null; | |||
|
136 | if (!value) { | |||
|
137 | if (d.defaultView && d.defaultView.getComputedStyle) { | |||
|
138 | var css = d.defaultView.getComputedStyle(elem, null); | |||
|
139 | cssProperty = cssProperty.replace(/([A-Z])/g, '-$1' | |||
|
140 | ).toLowerCase(); // from dojo.style.toSelectorCase | |||
|
141 | value = css ? css.getPropertyValue(cssProperty) : null; | |||
|
142 | } else if (elem.currentStyle) { | |||
|
143 | value = elem.currentStyle[cssProperty]; | |||
|
144 | } | |||
|
145 | } | |||
|
146 | if (cssProperty == 'opacity') { | |||
|
147 | value = parseFloat(value); | |||
|
148 | } | |||
|
149 | ||||
|
150 | if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.find(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) { | |||
|
151 | if (MochiKit.Style.getStyle(elem, 'position') == 'static') { | |||
|
152 | value = 'auto'; | |||
|
153 | } | |||
|
154 | } | |||
|
155 | ||||
|
156 | return value == 'auto' ? null : value; | |||
|
157 | }, | |||
|
158 | ||||
|
159 | /** @id MochiKit.Style.setStyle */ | |||
|
160 | setStyle: function (elem, style) { | |||
|
161 | elem = MochiKit.DOM.getElement(elem); | |||
|
162 | for (var name in style) { | |||
|
163 | if (name == 'opacity') { | |||
|
164 | MochiKit.Style.setOpacity(elem, style[name]); | |||
|
165 | } else { | |||
|
166 | elem.style[MochiKit.Base.camelize(name)] = style[name]; | |||
|
167 | } | |||
|
168 | } | |||
|
169 | }, | |||
|
170 | ||||
|
171 | /** @id MochiKit.Style.setOpacity */ | |||
|
172 | setOpacity: function (elem, o) { | |||
|
173 | elem = MochiKit.DOM.getElement(elem); | |||
|
174 | var self = MochiKit.Style; | |||
|
175 | if (o == 1) { | |||
|
176 | var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)); | |||
|
177 | elem.style["opacity"] = toSet ? 0.999999 : 1.0; | |||
|
178 | if (/MSIE/.test(navigator.userAgent)) { | |||
|
179 | elem.style['filter'] = | |||
|
180 | self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, ''); | |||
|
181 | } | |||
|
182 | } else { | |||
|
183 | if (o < 0.00001) { | |||
|
184 | o = 0; | |||
|
185 | } | |||
|
186 | elem.style["opacity"] = o; | |||
|
187 | if (/MSIE/.test(navigator.userAgent)) { | |||
|
188 | elem.style['filter'] = | |||
|
189 | self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')'; | |||
|
190 | } | |||
|
191 | } | |||
|
192 | }, | |||
|
193 | ||||
|
194 | /* | |||
|
195 | ||||
|
196 | getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0. | |||
|
197 | Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved. | |||
|
198 | License: BSD, http://developer.yahoo.net/yui/license.txt | |||
|
199 | ||||
|
200 | */ | |||
|
201 | ||||
|
202 | /** @id MochiKit.Style.getElementPosition */ | |||
|
203 | getElementPosition: function (elem, /* optional */relativeTo) { | |||
|
204 | var self = MochiKit.Style; | |||
|
205 | var dom = MochiKit.DOM; | |||
|
206 | elem = dom.getElement(elem); | |||
|
207 | ||||
|
208 | if (!elem || | |||
|
209 | (!(elem.x && elem.y) && | |||
|
210 | (!elem.parentNode === null || | |||
|
211 | self.getStyle(elem, 'display') == 'none'))) { | |||
|
212 | return undefined; | |||
|
213 | } | |||
|
214 | ||||
|
215 | var c = new self.Coordinates(0, 0); | |||
|
216 | var box = null; | |||
|
217 | var parent = null; | |||
|
218 | ||||
|
219 | var d = MochiKit.DOM._document; | |||
|
220 | var de = d.documentElement; | |||
|
221 | var b = d.body; | |||
|
222 | ||||
|
223 | if (!elem.parentNode && elem.x && elem.y) { | |||
|
224 | /* it's just a MochiKit.Style.Coordinates object */ | |||
|
225 | c.x += elem.x || 0; | |||
|
226 | c.y += elem.y || 0; | |||
|
227 | } else if (elem.getBoundingClientRect) { // IE shortcut | |||
|
228 | /* | |||
|
229 | ||||
|
230 | The IE shortcut can be off by two. We fix it. See: | |||
|
231 | http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp | |||
|
232 | ||||
|
233 | This is similar to the method used in | |||
|
234 | MochiKit.Signal.Event.mouse(). | |||
|
235 | ||||
|
236 | */ | |||
|
237 | box = elem.getBoundingClientRect(); | |||
|
238 | ||||
|
239 | c.x += box.left + | |||
|
240 | (de.scrollLeft || b.scrollLeft) - | |||
|
241 | (de.clientLeft || 0); | |||
|
242 | ||||
|
243 | c.y += box.top + | |||
|
244 | (de.scrollTop || b.scrollTop) - | |||
|
245 | (de.clientTop || 0); | |||
|
246 | ||||
|
247 | } else if (elem.offsetParent) { | |||
|
248 | c.x += elem.offsetLeft; | |||
|
249 | c.y += elem.offsetTop; | |||
|
250 | parent = elem.offsetParent; | |||
|
251 | ||||
|
252 | if (parent != elem) { | |||
|
253 | while (parent) { | |||
|
254 | c.x += parent.offsetLeft; | |||
|
255 | c.y += parent.offsetTop; | |||
|
256 | parent = parent.offsetParent; | |||
|
257 | } | |||
|
258 | } | |||
|
259 | ||||
|
260 | /* | |||
|
261 | ||||
|
262 | Opera < 9 and old Safari (absolute) incorrectly account for | |||
|
263 | body offsetTop and offsetLeft. | |||
|
264 | ||||
|
265 | */ | |||
|
266 | var ua = navigator.userAgent.toLowerCase(); | |||
|
267 | if ((typeof(opera) != 'undefined' && | |||
|
268 | parseFloat(opera.version()) < 9) || | |||
|
269 | (ua.indexOf('AppleWebKit') != -1 && | |||
|
270 | self.getStyle(elem, 'position') == 'absolute')) { | |||
|
271 | ||||
|
272 | c.x -= b.offsetLeft; | |||
|
273 | c.y -= b.offsetTop; | |||
|
274 | ||||
|
275 | } | |||
|
276 | } | |||
|
277 | ||||
|
278 | if (typeof(relativeTo) != 'undefined') { | |||
|
279 | relativeTo = arguments.callee(relativeTo); | |||
|
280 | if (relativeTo) { | |||
|
281 | c.x -= (relativeTo.x || 0); | |||
|
282 | c.y -= (relativeTo.y || 0); | |||
|
283 | } | |||
|
284 | } | |||
|
285 | ||||
|
286 | if (elem.parentNode) { | |||
|
287 | parent = elem.parentNode; | |||
|
288 | } else { | |||
|
289 | parent = null; | |||
|
290 | } | |||
|
291 | ||||
|
292 | while (parent) { | |||
|
293 | var tagName = parent.tagName.toUpperCase(); | |||
|
294 | if (tagName === 'BODY' || tagName === 'HTML') { | |||
|
295 | break; | |||
|
296 | } | |||
|
297 | var disp = self.getStyle(parent, 'display'); | |||
|
298 | // Handle strange Opera bug for some display | |||
|
299 | if (disp != 'inline' && disp != 'table-row') { | |||
|
300 | c.x -= parent.scrollLeft; | |||
|
301 | c.y -= parent.scrollTop; | |||
|
302 | } | |||
|
303 | if (parent.parentNode) { | |||
|
304 | parent = parent.parentNode; | |||
|
305 | } else { | |||
|
306 | parent = null; | |||
|
307 | } | |||
|
308 | } | |||
|
309 | ||||
|
310 | return c; | |||
|
311 | }, | |||
|
312 | ||||
|
313 | /** @id MochiKit.Style.setElementPosition */ | |||
|
314 | setElementPosition: function (elem, newPos/* optional */, units) { | |||
|
315 | elem = MochiKit.DOM.getElement(elem); | |||
|
316 | if (typeof(units) == 'undefined') { | |||
|
317 | units = 'px'; | |||
|
318 | } | |||
|
319 | var newStyle = {}; | |||
|
320 | var isUndefNull = MochiKit.Base.isUndefinedOrNull; | |||
|
321 | if (!isUndefNull(newPos.x)) { | |||
|
322 | newStyle['left'] = newPos.x + units; | |||
|
323 | } | |||
|
324 | if (!isUndefNull(newPos.y)) { | |||
|
325 | newStyle['top'] = newPos.y + units; | |||
|
326 | } | |||
|
327 | MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle}); | |||
|
328 | }, | |||
|
329 | ||||
|
330 | /** @id MochiKit.Style.getElementDimensions */ | |||
|
331 | getElementDimensions: function (elem) { | |||
|
332 | var self = MochiKit.Style; | |||
|
333 | var dom = MochiKit.DOM; | |||
|
334 | if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') { | |||
|
335 | return new self.Dimensions(elem.w || 0, elem.h || 0); | |||
|
336 | } | |||
|
337 | elem = dom.getElement(elem); | |||
|
338 | if (!elem) { | |||
|
339 | return undefined; | |||
|
340 | } | |||
|
341 | var disp = self.getStyle(elem, 'display'); | |||
|
342 | // display can be empty/undefined on WebKit/KHTML | |||
|
343 | if (disp != 'none' && disp !== '' && typeof(disp) != 'undefined') { | |||
|
344 | return new self.Dimensions(elem.offsetWidth || 0, | |||
|
345 | elem.offsetHeight || 0); | |||
|
346 | } | |||
|
347 | var s = elem.style; | |||
|
348 | var originalVisibility = s.visibility; | |||
|
349 | var originalPosition = s.position; | |||
|
350 | s.visibility = 'hidden'; | |||
|
351 | s.position = 'absolute'; | |||
|
352 | s.display = ''; | |||
|
353 | var originalWidth = elem.offsetWidth; | |||
|
354 | var originalHeight = elem.offsetHeight; | |||
|
355 | s.display = 'none'; | |||
|
356 | s.position = originalPosition; | |||
|
357 | s.visibility = originalVisibility; | |||
|
358 | return new self.Dimensions(originalWidth, originalHeight); | |||
|
359 | }, | |||
|
360 | ||||
|
361 | /** @id MochiKit.Style.setElementDimensions */ | |||
|
362 | setElementDimensions: function (elem, newSize/* optional */, units) { | |||
|
363 | elem = MochiKit.DOM.getElement(elem); | |||
|
364 | if (typeof(units) == 'undefined') { | |||
|
365 | units = 'px'; | |||
|
366 | } | |||
|
367 | var newStyle = {}; | |||
|
368 | var isUndefNull = MochiKit.Base.isUndefinedOrNull; | |||
|
369 | if (!isUndefNull(newSize.w)) { | |||
|
370 | newStyle['width'] = newSize.w + units; | |||
|
371 | } | |||
|
372 | if (!isUndefNull(newSize.h)) { | |||
|
373 | newStyle['height'] = newSize.h + units; | |||
|
374 | } | |||
|
375 | MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle}); | |||
|
376 | }, | |||
|
377 | ||||
|
378 | /** @id MochiKit.Style.setDisplayForElement */ | |||
|
379 | setDisplayForElement: function (display, element/*, ...*/) { | |||
|
380 | var elements = MochiKit.Base.extend(null, arguments, 1); | |||
|
381 | var getElement = MochiKit.DOM.getElement; | |||
|
382 | for (var i = 0; i < elements.length; i++) { | |||
|
383 | element = getElement(elements[i]); | |||
|
384 | if (element) { | |||
|
385 | element.style.display = display; | |||
|
386 | } | |||
|
387 | } | |||
|
388 | }, | |||
|
389 | ||||
|
390 | /** @id MochiKit.Style.getViewportDimensions */ | |||
|
391 | getViewportDimensions: function () { | |||
|
392 | var d = new MochiKit.Style.Dimensions(); | |||
|
393 | ||||
|
394 | var w = MochiKit.DOM._window; | |||
|
395 | var b = MochiKit.DOM._document.body; | |||
|
396 | ||||
|
397 | if (w.innerWidth) { | |||
|
398 | d.w = w.innerWidth; | |||
|
399 | d.h = w.innerHeight; | |||
|
400 | } else if (b.parentElement.clientWidth) { | |||
|
401 | d.w = b.parentElement.clientWidth; | |||
|
402 | d.h = b.parentElement.clientHeight; | |||
|
403 | } else if (b && b.clientWidth) { | |||
|
404 | d.w = b.clientWidth; | |||
|
405 | d.h = b.clientHeight; | |||
|
406 | } | |||
|
407 | return d; | |||
|
408 | }, | |||
|
409 | ||||
|
410 | /** @id MochiKit.Style.getViewportPosition */ | |||
|
411 | getViewportPosition: function () { | |||
|
412 | var c = new MochiKit.Style.Coordinates(0, 0); | |||
|
413 | var d = MochiKit.DOM._document; | |||
|
414 | var de = d.documentElement; | |||
|
415 | var db = d.body; | |||
|
416 | if (de && (de.scrollTop || de.scrollLeft)) { | |||
|
417 | c.x = de.scrollLeft; | |||
|
418 | c.y = de.scrollTop; | |||
|
419 | } else if (db) { | |||
|
420 | c.x = db.scrollLeft; | |||
|
421 | c.y = db.scrollTop; | |||
|
422 | } | |||
|
423 | return c; | |||
|
424 | }, | |||
|
425 | ||||
|
426 | __new__: function () { | |||
|
427 | var m = MochiKit.Base; | |||
|
428 | ||||
|
429 | this.elementPosition = this.getElementPosition; | |||
|
430 | this.elementDimensions = this.getElementDimensions; | |||
|
431 | ||||
|
432 | this.hideElement = m.partial(this.setDisplayForElement, 'none'); | |||
|
433 | this.showElement = m.partial(this.setDisplayForElement, 'block'); | |||
|
434 | ||||
|
435 | this.EXPORT_TAGS = { | |||
|
436 | ':common': this.EXPORT, | |||
|
437 | ':all': m.concat(this.EXPORT, this.EXPORT_OK) | |||
|
438 | }; | |||
|
439 | ||||
|
440 | m.nameFunctions(this); | |||
|
441 | } | |||
|
442 | }); | |||
|
443 | ||||
|
444 | MochiKit.Style.__new__(); | |||
|
445 | MochiKit.Base._exportSymbols(this, MochiKit.Style); |
@@ -0,0 +1,181 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.Test 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.Test'); | |||
|
13 | dojo.require('MochiKit.Base'); | |||
|
14 | } | |||
|
15 | ||||
|
16 | if (typeof(JSAN) != 'undefined') { | |||
|
17 | JSAN.use("MochiKit.Base", []); | |||
|
18 | } | |||
|
19 | ||||
|
20 | try { | |||
|
21 | if (typeof(MochiKit.Base) == 'undefined') { | |||
|
22 | throw ""; | |||
|
23 | } | |||
|
24 | } catch (e) { | |||
|
25 | throw "MochiKit.Test depends on MochiKit.Base!"; | |||
|
26 | } | |||
|
27 | ||||
|
28 | if (typeof(MochiKit.Test) == 'undefined') { | |||
|
29 | MochiKit.Test = {}; | |||
|
30 | } | |||
|
31 | ||||
|
32 | MochiKit.Test.NAME = "MochiKit.Test"; | |||
|
33 | MochiKit.Test.VERSION = "1.4"; | |||
|
34 | MochiKit.Test.__repr__ = function () { | |||
|
35 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
36 | }; | |||
|
37 | ||||
|
38 | MochiKit.Test.toString = function () { | |||
|
39 | return this.__repr__(); | |||
|
40 | }; | |||
|
41 | ||||
|
42 | ||||
|
43 | MochiKit.Test.EXPORT = ["runTests"]; | |||
|
44 | MochiKit.Test.EXPORT_OK = []; | |||
|
45 | ||||
|
46 | MochiKit.Test.runTests = function (obj) { | |||
|
47 | if (typeof(obj) == "string") { | |||
|
48 | obj = JSAN.use(obj); | |||
|
49 | } | |||
|
50 | var suite = new MochiKit.Test.Suite(); | |||
|
51 | suite.run(obj); | |||
|
52 | }; | |||
|
53 | ||||
|
54 | MochiKit.Test.Suite = function () { | |||
|
55 | this.testIndex = 0; | |||
|
56 | MochiKit.Base.bindMethods(this); | |||
|
57 | }; | |||
|
58 | ||||
|
59 | MochiKit.Test.Suite.prototype = { | |||
|
60 | run: function (obj) { | |||
|
61 | try { | |||
|
62 | obj(this); | |||
|
63 | } catch (e) { | |||
|
64 | this.traceback(e); | |||
|
65 | } | |||
|
66 | }, | |||
|
67 | traceback: function (e) { | |||
|
68 | var items = MochiKit.Iter.sorted(MochiKit.Base.items(e)); | |||
|
69 | print("not ok " + this.testIndex + " - Error thrown"); | |||
|
70 | for (var i = 0; i < items.length; i++) { | |||
|
71 | var kv = items[i]; | |||
|
72 | if (kv[0] == "stack") { | |||
|
73 | kv[1] = kv[1].split(/\n/)[0]; | |||
|
74 | } | |||
|
75 | this.print("# " + kv.join(": ")); | |||
|
76 | } | |||
|
77 | }, | |||
|
78 | print: function (s) { | |||
|
79 | print(s); | |||
|
80 | }, | |||
|
81 | is: function (got, expected, /* optional */message) { | |||
|
82 | var res = 1; | |||
|
83 | var msg = null; | |||
|
84 | try { | |||
|
85 | res = MochiKit.Base.compare(got, expected); | |||
|
86 | } catch (e) { | |||
|
87 | msg = "Can not compare " + typeof(got) + ":" + typeof(expected); | |||
|
88 | } | |||
|
89 | if (res) { | |||
|
90 | msg = "Expected value did not compare equal"; | |||
|
91 | } | |||
|
92 | if (!res) { | |||
|
93 | return this.testResult(true, message); | |||
|
94 | } | |||
|
95 | return this.testResult(false, message, | |||
|
96 | [[msg], ["got:", got], ["expected:", expected]]); | |||
|
97 | }, | |||
|
98 | ||||
|
99 | testResult: function (pass, msg, failures) { | |||
|
100 | this.testIndex += 1; | |||
|
101 | if (pass) { | |||
|
102 | this.print("ok " + this.testIndex + " - " + msg); | |||
|
103 | return; | |||
|
104 | } | |||
|
105 | this.print("not ok " + this.testIndex + " - " + msg); | |||
|
106 | if (failures) { | |||
|
107 | for (var i = 0; i < failures.length; i++) { | |||
|
108 | this.print("# " + failures[i].join(" ")); | |||
|
109 | } | |||
|
110 | } | |||
|
111 | }, | |||
|
112 | ||||
|
113 | isDeeply: function (got, expected, /* optional */message) { | |||
|
114 | var m = MochiKit.Base; | |||
|
115 | var res = 1; | |||
|
116 | try { | |||
|
117 | res = m.compare(got, expected); | |||
|
118 | } catch (e) { | |||
|
119 | // pass | |||
|
120 | } | |||
|
121 | if (res === 0) { | |||
|
122 | return this.ok(true, message); | |||
|
123 | } | |||
|
124 | var gk = m.keys(got); | |||
|
125 | var ek = m.keys(expected); | |||
|
126 | gk.sort(); | |||
|
127 | ek.sort(); | |||
|
128 | if (m.compare(gk, ek)) { | |||
|
129 | // differing keys | |||
|
130 | var cmp = {}; | |||
|
131 | var i; | |||
|
132 | for (i = 0; i < gk.length; i++) { | |||
|
133 | cmp[gk[i]] = "got"; | |||
|
134 | } | |||
|
135 | for (i = 0; i < ek.length; i++) { | |||
|
136 | if (ek[i] in cmp) { | |||
|
137 | delete cmp[ek[i]]; | |||
|
138 | } else { | |||
|
139 | cmp[ek[i]] = "expected"; | |||
|
140 | } | |||
|
141 | } | |||
|
142 | var diffkeys = m.keys(cmp); | |||
|
143 | diffkeys.sort(); | |||
|
144 | var gotkeys = []; | |||
|
145 | var expkeys = []; | |||
|
146 | while (diffkeys.length) { | |||
|
147 | var k = diffkeys.shift(); | |||
|
148 | if (k in Object.prototype) { | |||
|
149 | continue; | |||
|
150 | } | |||
|
151 | (cmp[k] == "got" ? gotkeys : expkeys).push(k); | |||
|
152 | } | |||
|
153 | ||||
|
154 | ||||
|
155 | } | |||
|
156 | ||||
|
157 | return this.testResult((!res), msg, | |||
|
158 | (msg ? [["got:", got], ["expected:", expected]] : undefined) | |||
|
159 | ); | |||
|
160 | }, | |||
|
161 | ||||
|
162 | ok: function (res, message) { | |||
|
163 | return this.testResult(res, message); | |||
|
164 | } | |||
|
165 | }; | |||
|
166 | ||||
|
167 | MochiKit.Test.__new__ = function () { | |||
|
168 | var m = MochiKit.Base; | |||
|
169 | ||||
|
170 | this.EXPORT_TAGS = { | |||
|
171 | ":common": this.EXPORT, | |||
|
172 | ":all": m.concat(this.EXPORT, this.EXPORT_OK) | |||
|
173 | }; | |||
|
174 | ||||
|
175 | m.nameFunctions(this); | |||
|
176 | ||||
|
177 | }; | |||
|
178 | ||||
|
179 | MochiKit.Test.__new__(); | |||
|
180 | ||||
|
181 | MochiKit.Base._exportSymbols(this, MochiKit.Test); |
This diff has been collapsed as it changes many lines, (1981 lines changed) Show them Hide them | |||||
@@ -0,0 +1,1981 b'' | |||||
|
1 | /*** | |||
|
2 | ||||
|
3 | MochiKit.Visual 1.4 | |||
|
4 | ||||
|
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | |||
|
6 | ||||
|
7 | (c) 2005 Bob Ippolito and others. All rights Reserved. | |||
|
8 | ||||
|
9 | ***/ | |||
|
10 | ||||
|
11 | if (typeof(dojo) != 'undefined') { | |||
|
12 | dojo.provide('MochiKit.Visual'); | |||
|
13 | dojo.require('MochiKit.Base'); | |||
|
14 | dojo.require('MochiKit.DOM'); | |||
|
15 | dojo.require('MochiKit.Style'); | |||
|
16 | dojo.require('MochiKit.Color'); | |||
|
17 | dojo.require('MochiKit.Position'); | |||
|
18 | } | |||
|
19 | ||||
|
20 | if (typeof(JSAN) != 'undefined') { | |||
|
21 | JSAN.use("MochiKit.Base", []); | |||
|
22 | JSAN.use("MochiKit.DOM", []); | |||
|
23 | JSAN.use("MochiKit.Style", []); | |||
|
24 | JSAN.use("MochiKit.Color", []); | |||
|
25 | JSAN.use("MochiKit.Position", []); | |||
|
26 | } | |||
|
27 | ||||
|
28 | try { | |||
|
29 | if (typeof(MochiKit.Base) === 'undefined' || | |||
|
30 | typeof(MochiKit.DOM) === 'undefined' || | |||
|
31 | typeof(MochiKit.Style) === 'undefined' || | |||
|
32 | typeof(MochiKit.Position) === 'undefined' || | |||
|
33 | typeof(MochiKit.Color) === 'undefined') { | |||
|
34 | throw ""; | |||
|
35 | } | |||
|
36 | } catch (e) { | |||
|
37 | throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM, MochiKit.Style, MochiKit.Position and MochiKit.Color!"; | |||
|
38 | } | |||
|
39 | ||||
|
40 | if (typeof(MochiKit.Visual) == "undefined") { | |||
|
41 | MochiKit.Visual = {}; | |||
|
42 | } | |||
|
43 | ||||
|
44 | MochiKit.Visual.NAME = "MochiKit.Visual"; | |||
|
45 | MochiKit.Visual.VERSION = "1.4"; | |||
|
46 | ||||
|
47 | MochiKit.Visual.__repr__ = function () { | |||
|
48 | return "[" + this.NAME + " " + this.VERSION + "]"; | |||
|
49 | }; | |||
|
50 | ||||
|
51 | MochiKit.Visual.toString = function () { | |||
|
52 | return this.__repr__(); | |||
|
53 | }; | |||
|
54 | ||||
|
55 | MochiKit.Visual._RoundCorners = function (e, options) { | |||
|
56 | e = MochiKit.DOM.getElement(e); | |||
|
57 | this._setOptions(options); | |||
|
58 | if (this.options.__unstable__wrapElement) { | |||
|
59 | e = this._doWrap(e); | |||
|
60 | } | |||
|
61 | ||||
|
62 | var color = this.options.color; | |||
|
63 | var C = MochiKit.Color.Color; | |||
|
64 | if (this.options.color === "fromElement") { | |||
|
65 | color = C.fromBackground(e); | |||
|
66 | } else if (!(color instanceof C)) { | |||
|
67 | color = C.fromString(color); | |||
|
68 | } | |||
|
69 | this.isTransparent = (color.asRGB().a <= 0); | |||
|
70 | ||||
|
71 | var bgColor = this.options.bgColor; | |||
|
72 | if (this.options.bgColor === "fromParent") { | |||
|
73 | bgColor = C.fromBackground(e.offsetParent); | |||
|
74 | } else if (!(bgColor instanceof C)) { | |||
|
75 | bgColor = C.fromString(bgColor); | |||
|
76 | } | |||
|
77 | ||||
|
78 | this._roundCornersImpl(e, color, bgColor); | |||
|
79 | }; | |||
|
80 | ||||
|
81 | MochiKit.Visual._RoundCorners.prototype = { | |||
|
82 | _doWrap: function (e) { | |||
|
83 | var parent = e.parentNode; | |||
|
84 | var doc = MochiKit.DOM.currentDocument(); | |||
|
85 | if (typeof(doc.defaultView) === "undefined" | |||
|
86 | || doc.defaultView === null) { | |||
|
87 | return e; | |||
|
88 | } | |||
|
89 | var style = doc.defaultView.getComputedStyle(e, null); | |||
|
90 | if (typeof(style) === "undefined" || style === null) { | |||
|
91 | return e; | |||
|
92 | } | |||
|
93 | var wrapper = MochiKit.DOM.DIV({"style": { | |||
|
94 | display: "block", | |||
|
95 | // convert padding to margin | |||
|
96 | marginTop: style.getPropertyValue("padding-top"), | |||
|
97 | marginRight: style.getPropertyValue("padding-right"), | |||
|
98 | marginBottom: style.getPropertyValue("padding-bottom"), | |||
|
99 | marginLeft: style.getPropertyValue("padding-left"), | |||
|
100 | // remove padding so the rounding looks right | |||
|
101 | padding: "0px" | |||
|
102 | /* | |||
|
103 | paddingRight: "0px", | |||
|
104 | paddingLeft: "0px" | |||
|
105 | */ | |||
|
106 | }}); | |||
|
107 | wrapper.innerHTML = e.innerHTML; | |||
|
108 | e.innerHTML = ""; | |||
|
109 | e.appendChild(wrapper); | |||
|
110 | return e; | |||
|
111 | }, | |||
|
112 | ||||
|
113 | _roundCornersImpl: function (e, color, bgColor) { | |||
|
114 | if (this.options.border) { | |||
|
115 | this._renderBorder(e, bgColor); | |||
|
116 | } | |||
|
117 | if (this._isTopRounded()) { | |||
|
118 | this._roundTopCorners(e, color, bgColor); | |||
|
119 | } | |||
|
120 | if (this._isBottomRounded()) { | |||
|
121 | this._roundBottomCorners(e, color, bgColor); | |||
|
122 | } | |||
|
123 | }, | |||
|
124 | ||||
|
125 | _renderBorder: function (el, bgColor) { | |||
|
126 | var borderValue = "1px solid " + this._borderColor(bgColor); | |||
|
127 | var borderL = "border-left: " + borderValue; | |||
|
128 | var borderR = "border-right: " + borderValue; | |||
|
129 | var style = "style='" + borderL + ";" + borderR + "'"; | |||
|
130 | el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>"; | |||
|
131 | }, | |||
|
132 | ||||
|
133 | _roundTopCorners: function (el, color, bgColor) { | |||
|
134 | var corner = this._createCorner(bgColor); | |||
|
135 | for (var i = 0; i < this.options.numSlices; i++) { | |||
|
136 | corner.appendChild( | |||
|
137 | this._createCornerSlice(color, bgColor, i, "top") | |||
|
138 | ); | |||
|
139 | } | |||
|
140 | el.style.paddingTop = 0; | |||
|
141 | el.insertBefore(corner, el.firstChild); | |||
|
142 | }, | |||
|
143 | ||||
|
144 | _roundBottomCorners: function (el, color, bgColor) { | |||
|
145 | var corner = this._createCorner(bgColor); | |||
|
146 | for (var i = (this.options.numSlices - 1); i >= 0; i--) { | |||
|
147 | corner.appendChild( | |||
|
148 | this._createCornerSlice(color, bgColor, i, "bottom") | |||
|
149 | ); | |||
|
150 | } | |||
|
151 | el.style.paddingBottom = 0; | |||
|
152 | el.appendChild(corner); | |||
|
153 | }, | |||
|
154 | ||||
|
155 | _createCorner: function (bgColor) { | |||
|
156 | var dom = MochiKit.DOM; | |||
|
157 | return dom.DIV({style: {backgroundColor: bgColor.toString()}}); | |||
|
158 | }, | |||
|
159 | ||||
|
160 | _createCornerSlice: function (color, bgColor, n, position) { | |||
|
161 | var slice = MochiKit.DOM.SPAN(); | |||
|
162 | ||||
|
163 | var inStyle = slice.style; | |||
|
164 | inStyle.backgroundColor = color.toString(); | |||
|
165 | inStyle.display = "block"; | |||
|
166 | inStyle.height = "1px"; | |||
|
167 | inStyle.overflow = "hidden"; | |||
|
168 | inStyle.fontSize = "1px"; | |||
|
169 | ||||
|
170 | var borderColor = this._borderColor(color, bgColor); | |||
|
171 | if (this.options.border && n === 0) { | |||
|
172 | inStyle.borderTopStyle = "solid"; | |||
|
173 | inStyle.borderTopWidth = "1px"; | |||
|
174 | inStyle.borderLeftWidth = "0px"; | |||
|
175 | inStyle.borderRightWidth = "0px"; | |||
|
176 | inStyle.borderBottomWidth = "0px"; | |||
|
177 | // assumes css compliant box model | |||
|
178 | inStyle.height = "0px"; | |||
|
179 | inStyle.borderColor = borderColor.toString(); | |||
|
180 | } else if (borderColor) { | |||
|
181 | inStyle.borderColor = borderColor.toString(); | |||
|
182 | inStyle.borderStyle = "solid"; | |||
|
183 | inStyle.borderWidth = "0px 1px"; | |||
|
184 | } | |||
|
185 | ||||
|
186 | if (!this.options.compact && (n == (this.options.numSlices - 1))) { | |||
|
187 | inStyle.height = "2px"; | |||
|
188 | } | |||
|
189 | ||||
|
190 | this._setMargin(slice, n, position); | |||
|
191 | this._setBorder(slice, n, position); | |||
|
192 | ||||
|
193 | return slice; | |||
|
194 | }, | |||
|
195 | ||||
|
196 | _setOptions: function (options) { | |||
|
197 | this.options = { | |||
|
198 | corners: "all", | |||
|
199 | color: "fromElement", | |||
|
200 | bgColor: "fromParent", | |||
|
201 | blend: true, | |||
|
202 | border: false, | |||
|
203 | compact: false, | |||
|
204 | __unstable__wrapElement: false | |||
|
205 | }; | |||
|
206 | MochiKit.Base.update(this.options, options); | |||
|
207 | ||||
|
208 | this.options.numSlices = (this.options.compact ? 2 : 4); | |||
|
209 | }, | |||
|
210 | ||||
|
211 | _whichSideTop: function () { | |||
|
212 | var corners = this.options.corners; | |||
|
213 | if (this._hasString(corners, "all", "top")) { | |||
|
214 | return ""; | |||
|
215 | } | |||
|
216 | ||||
|
217 | var has_tl = (corners.indexOf("tl") != -1); | |||
|
218 | var has_tr = (corners.indexOf("tr") != -1); | |||
|
219 | if (has_tl && has_tr) { | |||
|
220 | return ""; | |||
|
221 | } | |||
|
222 | if (has_tl) { | |||
|
223 | return "left"; | |||
|
224 | } | |||
|
225 | if (has_tr) { | |||
|
226 | return "right"; | |||
|
227 | } | |||
|
228 | return ""; | |||
|
229 | }, | |||
|
230 | ||||
|
231 | _whichSideBottom: function () { | |||
|
232 | var corners = this.options.corners; | |||
|
233 | if (this._hasString(corners, "all", "bottom")) { | |||
|
234 | return ""; | |||
|
235 | } | |||
|
236 | ||||
|
237 | var has_bl = (corners.indexOf('bl') != -1); | |||
|
238 | var has_br = (corners.indexOf('br') != -1); | |||
|
239 | if (has_bl && has_br) { | |||
|
240 | return ""; | |||
|
241 | } | |||
|
242 | if (has_bl) { | |||
|
243 | return "left"; | |||
|
244 | } | |||
|
245 | if (has_br) { | |||
|
246 | return "right"; | |||
|
247 | } | |||
|
248 | return ""; | |||
|
249 | }, | |||
|
250 | ||||
|
251 | _borderColor: function (color, bgColor) { | |||
|
252 | if (color == "transparent") { | |||
|
253 | return bgColor; | |||
|
254 | } else if (this.options.border) { | |||
|
255 | return this.options.border; | |||
|
256 | } else if (this.options.blend) { | |||
|
257 | return bgColor.blendedColor(color); | |||
|
258 | } | |||
|
259 | return ""; | |||
|
260 | }, | |||
|
261 | ||||
|
262 | ||||
|
263 | _setMargin: function (el, n, corners) { | |||
|
264 | var marginSize = this._marginSize(n) + "px"; | |||
|
265 | var whichSide = ( | |||
|
266 | corners == "top" ? this._whichSideTop() : this._whichSideBottom() | |||
|
267 | ); | |||
|
268 | var style = el.style; | |||
|
269 | ||||
|
270 | if (whichSide == "left") { | |||
|
271 | style.marginLeft = marginSize; | |||
|
272 | style.marginRight = "0px"; | |||
|
273 | } else if (whichSide == "right") { | |||
|
274 | style.marginRight = marginSize; | |||
|
275 | style.marginLeft = "0px"; | |||
|
276 | } else { | |||
|
277 | style.marginLeft = marginSize; | |||
|
278 | style.marginRight = marginSize; | |||
|
279 | } | |||
|
280 | }, | |||
|
281 | ||||
|
282 | _setBorder: function (el, n, corners) { | |||
|
283 | var borderSize = this._borderSize(n) + "px"; | |||
|
284 | var whichSide = ( | |||
|
285 | corners == "top" ? this._whichSideTop() : this._whichSideBottom() | |||
|
286 | ); | |||
|
287 | ||||
|
288 | var style = el.style; | |||
|
289 | if (whichSide == "left") { | |||
|
290 | style.borderLeftWidth = borderSize; | |||
|
291 | style.borderRightWidth = "0px"; | |||
|
292 | } else if (whichSide == "right") { | |||
|
293 | style.borderRightWidth = borderSize; | |||
|
294 | style.borderLeftWidth = "0px"; | |||
|
295 | } else { | |||
|
296 | style.borderLeftWidth = borderSize; | |||
|
297 | style.borderRightWidth = borderSize; | |||
|
298 | } | |||
|
299 | }, | |||
|
300 | ||||
|
301 | _marginSize: function (n) { | |||
|
302 | if (this.isTransparent) { | |||
|
303 | return 0; | |||
|
304 | } | |||
|
305 | ||||
|
306 | var o = this.options; | |||
|
307 | if (o.compact && o.blend) { | |||
|
308 | var smBlendedMarginSizes = [1, 0]; | |||
|
309 | return smBlendedMarginSizes[n]; | |||
|
310 | } else if (o.compact) { | |||
|
311 | var compactMarginSizes = [2, 1]; | |||
|
312 | return compactMarginSizes[n]; | |||
|
313 | } else if (o.blend) { | |||
|
314 | var blendedMarginSizes = [3, 2, 1, 0]; | |||
|
315 | return blendedMarginSizes[n]; | |||
|
316 | } else { | |||
|
317 | var marginSizes = [5, 3, 2, 1]; | |||
|
318 | return marginSizes[n]; | |||
|
319 | } | |||
|
320 | }, | |||
|
321 | ||||
|
322 | _borderSize: function (n) { | |||
|
323 | var o = this.options; | |||
|
324 | var borderSizes; | |||
|
325 | if (o.compact && (o.blend || this.isTransparent)) { | |||
|
326 | return 1; | |||
|
327 | } else if (o.compact) { | |||
|
328 | borderSizes = [1, 0]; | |||
|
329 | } else if (o.blend) { | |||
|
330 | borderSizes = [2, 1, 1, 1]; | |||
|
331 | } else if (o.border) { | |||
|
332 | borderSizes = [0, 2, 0, 0]; | |||
|
333 | } else if (this.isTransparent) { | |||
|
334 | borderSizes = [5, 3, 2, 1]; | |||
|
335 | } else { | |||
|
336 | return 0; | |||
|
337 | } | |||
|
338 | return borderSizes[n]; | |||
|
339 | }, | |||
|
340 | ||||
|
341 | _hasString: function (str) { | |||
|
342 | for (var i = 1; i< arguments.length; i++) { | |||
|
343 | if (str.indexOf(arguments[i]) != -1) { | |||
|
344 | return true; | |||
|
345 | } | |||
|
346 | } | |||
|
347 | return false; | |||
|
348 | }, | |||
|
349 | ||||
|
350 | _isTopRounded: function () { | |||
|
351 | return this._hasString(this.options.corners, | |||
|
352 | "all", "top", "tl", "tr" | |||
|
353 | ); | |||
|
354 | }, | |||
|
355 | ||||
|
356 | _isBottomRounded: function () { | |||
|
357 | return this._hasString(this.options.corners, | |||
|
358 | "all", "bottom", "bl", "br" | |||
|
359 | ); | |||
|
360 | }, | |||
|
361 | ||||
|
362 | _hasSingleTextChild: function (el) { | |||
|
363 | return (el.childNodes.length == 1 && el.childNodes[0].nodeType == 3); | |||
|
364 | } | |||
|
365 | }; | |||
|
366 | ||||
|
367 | /** @id MochiKit.Visual.roundElement */ | |||
|
368 | MochiKit.Visual.roundElement = function (e, options) { | |||
|
369 | new MochiKit.Visual._RoundCorners(e, options); | |||
|
370 | }; | |||
|
371 | ||||
|
372 | /** @id MochiKit.Visual.roundClass */ | |||
|
373 | MochiKit.Visual.roundClass = function (tagName, className, options) { | |||
|
374 | var elements = MochiKit.DOM.getElementsByTagAndClassName( | |||
|
375 | tagName, className | |||
|
376 | ); | |||
|
377 | for (var i = 0; i < elements.length; i++) { | |||
|
378 | MochiKit.Visual.roundElement(elements[i], options); | |||
|
379 | } | |||
|
380 | }; | |||
|
381 | ||||
|
382 | /** @id MochiKit.Visual.tagifyText */ | |||
|
383 | MochiKit.Visual.tagifyText = function (element, /* optional */tagifyStyle) { | |||
|
384 | /*** | |||
|
385 | ||||
|
386 | Change a node text to character in tags. | |||
|
387 | ||||
|
388 | @param tagifyStyle: the style to apply to character nodes, default to | |||
|
389 | 'position: relative'. | |||
|
390 | ||||
|
391 | ***/ | |||
|
392 | tagifyStyle = tagifyStyle || 'position:relative'; | |||
|
393 | if (/MSIE/.test(navigator.userAgent)) { | |||
|
394 | tagifyStyle += ';zoom:1'; | |||
|
395 | } | |||
|
396 | element = MochiKit.DOM.getElement(element); | |||
|
397 | var ma = MochiKit.Base.map; | |||
|
398 | ma(function (child) { | |||
|
399 | if (child.nodeType == 3) { | |||
|
400 | ma(function (character) { | |||
|
401 | element.insertBefore( | |||
|
402 | MochiKit.DOM.SPAN({style: tagifyStyle}, | |||
|
403 | character == ' ' ? String.fromCharCode(160) : character), child); | |||
|
404 | }, child.nodeValue.split('')); | |||
|
405 | MochiKit.DOM.removeElement(child); | |||
|
406 | } | |||
|
407 | }, element.childNodes); | |||
|
408 | }; | |||
|
409 | ||||
|
410 | /** @id MochiKit.Visual.forceRerendering */ | |||
|
411 | MochiKit.Visual.forceRerendering = function (element) { | |||
|
412 | try { | |||
|
413 | element = MochiKit.DOM.getElement(element); | |||
|
414 | var n = document.createTextNode(' '); | |||
|
415 | element.appendChild(n); | |||
|
416 | element.removeChild(n); | |||
|
417 | } catch(e) { | |||
|
418 | } | |||
|
419 | }; | |||
|
420 | ||||
|
421 | /** @id MochiKit.Visual.multiple */ | |||
|
422 | MochiKit.Visual.multiple = function (elements, effect, /* optional */options) { | |||
|
423 | /*** | |||
|
424 | ||||
|
425 | Launch the same effect subsequently on given elements. | |||
|
426 | ||||
|
427 | ***/ | |||
|
428 | options = MochiKit.Base.update({ | |||
|
429 | speed: 0.1, delay: 0.0 | |||
|
430 | }, options); | |||
|
431 | var masterDelay = options.delay; | |||
|
432 | var index = 0; | |||
|
433 | MochiKit.Base.map(function (innerelement) { | |||
|
434 | options.delay = index * options.speed + masterDelay; | |||
|
435 | new effect(innerelement, options); | |||
|
436 | index += 1; | |||
|
437 | }, elements); | |||
|
438 | }; | |||
|
439 | ||||
|
440 | MochiKit.Visual.PAIRS = { | |||
|
441 | 'slide': ['slideDown', 'slideUp'], | |||
|
442 | 'blind': ['blindDown', 'blindUp'], | |||
|
443 | 'appear': ['appear', 'fade'], | |||
|
444 | 'size': ['grow', 'shrink'] | |||
|
445 | }; | |||
|
446 | ||||
|
447 | /** @id MochiKit.Visual.toggle */ | |||
|
448 | MochiKit.Visual.toggle = function (element, /* optional */effect, /* optional */options) { | |||
|
449 | /*** | |||
|
450 | ||||
|
451 | Toggle an item between two state depending of its visibility, making | |||
|
452 | a effect between these states. Default effect is 'appear', can be | |||
|
453 | 'slide' or 'blind'. | |||
|
454 | ||||
|
455 | ***/ | |||
|
456 | element = MochiKit.DOM.getElement(element); | |||
|
457 | effect = (effect || 'appear').toLowerCase(); | |||
|
458 | options = MochiKit.Base.update({ | |||
|
459 | queue: {position: 'end', scope: (element.id || 'global'), limit: 1} | |||
|
460 | }, options); | |||
|
461 | var v = MochiKit.Visual; | |||
|
462 | v[MochiKit.Style.getStyle(element, 'display') != 'none' ? | |||
|
463 | v.PAIRS[effect][1] : v.PAIRS[effect][0]](element, options); | |||
|
464 | }; | |||
|
465 | ||||
|
466 | /*** | |||
|
467 | ||||
|
468 | Transitions: define functions calculating variations depending of a position. | |||
|
469 | ||||
|
470 | ***/ | |||
|
471 | ||||
|
472 | MochiKit.Visual.Transitions = {}; | |||
|
473 | ||||
|
474 | /** @id MochiKit.Visual.Transitions.linear */ | |||
|
475 | MochiKit.Visual.Transitions.linear = function (pos) { | |||
|
476 | return pos; | |||
|
477 | }; | |||
|
478 | ||||
|
479 | /** @id MochiKit.Visual.Transitions.sinoidal */ | |||
|
480 | MochiKit.Visual.Transitions.sinoidal = function (pos) { | |||
|
481 | return (-Math.cos(pos*Math.PI)/2) + 0.5; | |||
|
482 | }; | |||
|
483 | ||||
|
484 | /** @id MochiKit.Visual.Transitions.reverse */ | |||
|
485 | MochiKit.Visual.Transitions.reverse = function (pos) { | |||
|
486 | return 1 - pos; | |||
|
487 | }; | |||
|
488 | ||||
|
489 | /** @id MochiKit.Visual.Transitions.flicker */ | |||
|
490 | MochiKit.Visual.Transitions.flicker = function (pos) { | |||
|
491 | return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; | |||
|
492 | }; | |||
|
493 | ||||
|
494 | /** @id MochiKit.Visual.Transitions.wobble */ | |||
|
495 | MochiKit.Visual.Transitions.wobble = function (pos) { | |||
|
496 | return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; | |||
|
497 | }; | |||
|
498 | ||||
|
499 | /** @id MochiKit.Visual.Transitions.pulse */ | |||
|
500 | MochiKit.Visual.Transitions.pulse = function (pos, pulses) { | |||
|
501 | if (!pulses) { | |||
|
502 | return (Math.floor(pos*10) % 2 === 0 ? | |||
|
503 | (pos*10 - Math.floor(pos*10)) : 1 - (pos*10 - Math.floor(pos*10))); | |||
|
504 | } | |||
|
505 | return (Math.round((pos % (1/pulses)) * pulses) == 0 ? | |||
|
506 | ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) : | |||
|
507 | 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))); | |||
|
508 | }; | |||
|
509 | ||||
|
510 | /** @id MochiKit.Visual.Transitions.none */ | |||
|
511 | MochiKit.Visual.Transitions.none = function (pos) { | |||
|
512 | return 0; | |||
|
513 | }; | |||
|
514 | ||||
|
515 | /** @id MochiKit.Visual.Transitions.full */ | |||
|
516 | MochiKit.Visual.Transitions.full = function (pos) { | |||
|
517 | return 1; | |||
|
518 | }; | |||
|
519 | ||||
|
520 | /*** | |||
|
521 | ||||
|
522 | Core effects | |||
|
523 | ||||
|
524 | ***/ | |||
|
525 | ||||
|
526 | MochiKit.Visual.ScopedQueue = function () { | |||
|
527 | var cls = arguments.callee; | |||
|
528 | if (!(this instanceof cls)) { | |||
|
529 | return new cls(); | |||
|
530 | } | |||
|
531 | this.__init__(); | |||
|
532 | }; | |||
|
533 | ||||
|
534 | MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype, { | |||
|
535 | __init__: function () { | |||
|
536 | this.effects = []; | |||
|
537 | this.interval = null; | |||
|
538 | }, | |||
|
539 | ||||
|
540 | /** @id MochiKit.Visual.ScopedQueue.prototype.add */ | |||
|
541 | add: function (effect) { | |||
|
542 | var timestamp = new Date().getTime(); | |||
|
543 | ||||
|
544 | var position = (typeof(effect.options.queue) == 'string') ? | |||
|
545 | effect.options.queue : effect.options.queue.position; | |||
|
546 | ||||
|
547 | var ma = MochiKit.Base.map; | |||
|
548 | switch (position) { | |||
|
549 | case 'front': | |||
|
550 | // move unstarted effects after this effect | |||
|
551 | ma(function (e) { | |||
|
552 | if (e.state == 'idle') { | |||
|
553 | e.startOn += effect.finishOn; | |||
|
554 | e.finishOn += effect.finishOn; | |||
|
555 | } | |||
|
556 | }, this.effects); | |||
|
557 | break; | |||
|
558 | case 'end': | |||
|
559 | var finish; | |||
|
560 | // start effect after last queued effect has finished | |||
|
561 | ma(function (e) { | |||
|
562 | var i = e.finishOn; | |||
|
563 | if (i >= (finish || i)) { | |||
|
564 | finish = i; | |||
|
565 | } | |||
|
566 | }, this.effects); | |||
|
567 | timestamp = finish || timestamp; | |||
|
568 | break; | |||
|
569 | case 'break': | |||
|
570 | ma(function (e) { | |||
|
571 | e.finalize(); | |||
|
572 | }, this.effects); | |||
|
573 | break; | |||
|
574 | } | |||
|
575 | ||||
|
576 | effect.startOn += timestamp; | |||
|
577 | effect.finishOn += timestamp; | |||
|
578 | if (!effect.options.queue.limit || | |||
|
579 | this.effects.length < effect.options.queue.limit) { | |||
|
580 | this.effects.push(effect); | |||
|
581 | } | |||
|
582 | ||||
|
583 | if (!this.interval) { | |||
|
584 | this.interval = this.startLoop(MochiKit.Base.bind(this.loop, this), | |||
|
585 | 40); | |||
|
586 | } | |||
|
587 | }, | |||
|
588 | ||||
|
589 | /** @id MochiKit.Visual.ScopedQueue.prototype.startLoop */ | |||
|
590 | startLoop: function (func, interval) { | |||
|
591 | return setInterval(func, interval); | |||
|
592 | }, | |||
|
593 | ||||
|
594 | /** @id MochiKit.Visual.ScopedQueue.prototype.remove */ | |||
|
595 | remove: function (effect) { | |||
|
596 | this.effects = MochiKit.Base.filter(function (e) { | |||
|
597 | return e != effect; | |||
|
598 | }, this.effects); | |||
|
599 | if (!this.effects.length) { | |||
|
600 | this.stopLoop(this.interval); | |||
|
601 | this.interval = null; | |||
|
602 | } | |||
|
603 | }, | |||
|
604 | ||||
|
605 | /** @id MochiKit.Visual.ScopedQueue.prototype.stopLoop */ | |||
|
606 | stopLoop: function (interval) { | |||
|
607 | clearInterval(interval); | |||
|
608 | }, | |||
|
609 | ||||
|
610 | /** @id MochiKit.Visual.ScopedQueue.prototype.loop */ | |||
|
611 | loop: function () { | |||
|
612 | var timePos = new Date().getTime(); | |||
|
613 | MochiKit.Base.map(function (effect) { | |||
|
614 | effect.loop(timePos); | |||
|
615 | }, this.effects); | |||
|
616 | } | |||
|
617 | }); | |||
|
618 | ||||
|
619 | MochiKit.Visual.Queues = { | |||
|
620 | instances: {}, | |||
|
621 | ||||
|
622 | get: function (queueName) { | |||
|
623 | if (typeof(queueName) != 'string') { | |||
|
624 | return queueName; | |||
|
625 | } | |||
|
626 | ||||
|
627 | if (!this.instances[queueName]) { | |||
|
628 | this.instances[queueName] = new MochiKit.Visual.ScopedQueue(); | |||
|
629 | } | |||
|
630 | return this.instances[queueName]; | |||
|
631 | } | |||
|
632 | }; | |||
|
633 | ||||
|
634 | MochiKit.Visual.Queue = MochiKit.Visual.Queues.get('global'); | |||
|
635 | ||||
|
636 | MochiKit.Visual.DefaultOptions = { | |||
|
637 | transition: MochiKit.Visual.Transitions.sinoidal, | |||
|
638 | duration: 1.0, // seconds | |||
|
639 | fps: 25.0, // max. 25fps due to MochiKit.Visual.Queue implementation | |||
|
640 | sync: false, // true for combining | |||
|
641 | from: 0.0, | |||
|
642 | to: 1.0, | |||
|
643 | delay: 0.0, | |||
|
644 | queue: 'parallel' | |||
|
645 | }; | |||
|
646 | ||||
|
647 | MochiKit.Visual.Base = function () {}; | |||
|
648 | ||||
|
649 | MochiKit.Visual.Base.prototype = { | |||
|
650 | /*** | |||
|
651 | ||||
|
652 | Basic class for all Effects. Define a looping mechanism called for each step | |||
|
653 | of an effect. Don't instantiate it, only subclass it. | |||
|
654 | ||||
|
655 | ***/ | |||
|
656 | ||||
|
657 | __class__ : MochiKit.Visual.Base, | |||
|
658 | ||||
|
659 | /** @id MochiKit.Visual.Base.prototype.start */ | |||
|
660 | start: function (options) { | |||
|
661 | var v = MochiKit.Visual; | |||
|
662 | this.options = MochiKit.Base.setdefault(options, | |||
|
663 | v.DefaultOptions); | |||
|
664 | this.currentFrame = 0; | |||
|
665 | this.state = 'idle'; | |||
|
666 | this.startOn = this.options.delay*1000; | |||
|
667 | this.finishOn = this.startOn + (this.options.duration*1000); | |||
|
668 | this.event('beforeStart'); | |||
|
669 | if (!this.options.sync) { | |||
|
670 | v.Queues.get(typeof(this.options.queue) == 'string' ? | |||
|
671 | 'global' : this.options.queue.scope).add(this); | |||
|
672 | } | |||
|
673 | }, | |||
|
674 | ||||
|
675 | /** @id MochiKit.Visual.Base.prototype.loop */ | |||
|
676 | loop: function (timePos) { | |||
|
677 | if (timePos >= this.startOn) { | |||
|
678 | if (timePos >= this.finishOn) { | |||
|
679 | return this.finalize(); | |||
|
680 | } | |||
|
681 | var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); | |||
|
682 | var frame = | |||
|
683 | Math.round(pos * this.options.fps * this.options.duration); | |||
|
684 | if (frame > this.currentFrame) { | |||
|
685 | this.render(pos); | |||
|
686 | this.currentFrame = frame; | |||
|
687 | } | |||
|
688 | } | |||
|
689 | }, | |||
|
690 | ||||
|
691 | /** @id MochiKit.Visual.Base.prototype.render */ | |||
|
692 | render: function (pos) { | |||
|
693 | if (this.state == 'idle') { | |||
|
694 | this.state = 'running'; | |||
|
695 | this.event('beforeSetup'); | |||
|
696 | this.setup(); | |||
|
697 | this.event('afterSetup'); | |||
|
698 | } | |||
|
699 | if (this.state == 'running') { | |||
|
700 | if (this.options.transition) { | |||
|
701 | pos = this.options.transition(pos); | |||
|
702 | } | |||
|
703 | pos *= (this.options.to - this.options.from); | |||
|
704 | pos += this.options.from; | |||
|
705 | this.event('beforeUpdate'); | |||
|
706 | this.update(pos); | |||
|
707 | this.event('afterUpdate'); | |||
|
708 | } | |||
|
709 | }, | |||
|
710 | ||||
|
711 | /** @id MochiKit.Visual.Base.prototype.cancel */ | |||
|
712 | cancel: function () { | |||
|
713 | if (!this.options.sync) { | |||
|
714 | MochiKit.Visual.Queues.get(typeof(this.options.queue) == 'string' ? | |||
|
715 | 'global' : this.options.queue.scope).remove(this); | |||
|
716 | } | |||
|
717 | this.state = 'finished'; | |||
|
718 | }, | |||
|
719 | ||||
|
720 | /** @id MochiKit.Visual.Base.prototype.finalize */ | |||
|
721 | finalize: function () { | |||
|
722 | this.render(1.0); | |||
|
723 | this.cancel(); | |||
|
724 | this.event('beforeFinish'); | |||
|
725 | this.finish(); | |||
|
726 | this.event('afterFinish'); | |||
|
727 | }, | |||
|
728 | ||||
|
729 | setup: function () { | |||
|
730 | }, | |||
|
731 | ||||
|
732 | finish: function () { | |||
|
733 | }, | |||
|
734 | ||||
|
735 | update: function (position) { | |||
|
736 | }, | |||
|
737 | ||||
|
738 | /** @id MochiKit.Visual.Base.prototype.event */ | |||
|
739 | event: function (eventName) { | |||
|
740 | if (this.options[eventName + 'Internal']) { | |||
|
741 | this.options[eventName + 'Internal'](this); | |||
|
742 | } | |||
|
743 | if (this.options[eventName]) { | |||
|
744 | this.options[eventName](this); | |||
|
745 | } | |||
|
746 | }, | |||
|
747 | ||||
|
748 | /** @id MochiKit.Visual.Base.prototype.repr */ | |||
|
749 | repr: function () { | |||
|
750 | return '[' + this.__class__.NAME + ', options:' + | |||
|
751 | MochiKit.Base.repr(this.options) + ']'; | |||
|
752 | } | |||
|
753 | }; | |||
|
754 | ||||
|
755 | /** @id MochiKit.Visual.Parallel */ | |||
|
756 | MochiKit.Visual.Parallel = function (effects, options) { | |||
|
757 | var cls = arguments.callee; | |||
|
758 | if (!(this instanceof cls)) { | |||
|
759 | return new cls(effects, options); | |||
|
760 | } | |||
|
761 | ||||
|
762 | this.__init__(effects, options); | |||
|
763 | }; | |||
|
764 | ||||
|
765 | MochiKit.Visual.Parallel.prototype = new MochiKit.Visual.Base(); | |||
|
766 | ||||
|
767 | MochiKit.Base.update(MochiKit.Visual.Parallel.prototype, { | |||
|
768 | /*** | |||
|
769 | ||||
|
770 | Run multiple effects at the same time. | |||
|
771 | ||||
|
772 | ***/ | |||
|
773 | ||||
|
774 | __class__ : MochiKit.Visual.Parallel, | |||
|
775 | ||||
|
776 | __init__: function (effects, options) { | |||
|
777 | this.effects = effects || []; | |||
|
778 | this.start(options); | |||
|
779 | }, | |||
|
780 | ||||
|
781 | /** @id MochiKit.Visual.Parallel.prototype.update */ | |||
|
782 | update: function (position) { | |||
|
783 | MochiKit.Base.map(function (effect) { | |||
|
784 | effect.render(position); | |||
|
785 | }, this.effects); | |||
|
786 | }, | |||
|
787 | ||||
|
788 | /** @id MochiKit.Visual.Parallel.prototype.finish */ | |||
|
789 | finish: function () { | |||
|
790 | MochiKit.Base.map(function (effect) { | |||
|
791 | effect.finalize(); | |||
|
792 | }, this.effects); | |||
|
793 | } | |||
|
794 | }); | |||
|
795 | ||||
|
796 | /** @id MochiKit.Visual.Opacity */ | |||
|
797 | MochiKit.Visual.Opacity = function (element, options) { | |||
|
798 | var cls = arguments.callee; | |||
|
799 | if (!(this instanceof cls)) { | |||
|
800 | return new cls(element, options); | |||
|
801 | } | |||
|
802 | this.__init__(element, options); | |||
|
803 | }; | |||
|
804 | ||||
|
805 | MochiKit.Visual.Opacity.prototype = new MochiKit.Visual.Base(); | |||
|
806 | ||||
|
807 | MochiKit.Base.update(MochiKit.Visual.Opacity.prototype, { | |||
|
808 | /*** | |||
|
809 | ||||
|
810 | Change the opacity of an element. | |||
|
811 | ||||
|
812 | @param options: 'from' and 'to' change the starting and ending opacities. | |||
|
813 | Must be between 0.0 and 1.0. Default to current opacity and 1.0. | |||
|
814 | ||||
|
815 | ***/ | |||
|
816 | ||||
|
817 | __class__ : MochiKit.Visual.Opacity, | |||
|
818 | ||||
|
819 | __init__: function (element, /* optional */options) { | |||
|
820 | var b = MochiKit.Base; | |||
|
821 | var s = MochiKit.Style; | |||
|
822 | this.element = MochiKit.DOM.getElement(element); | |||
|
823 | // make this work on IE on elements without 'layout' | |||
|
824 | if (this.element.currentStyle && | |||
|
825 | (!this.element.currentStyle.hasLayout)) { | |||
|
826 | s.setStyle(this.element, {zoom: 1}); | |||
|
827 | } | |||
|
828 | options = b.update({ | |||
|
829 | from: s.getStyle(this.element, 'opacity') || 0.0, | |||
|
830 | to: 1.0 | |||
|
831 | }, options); | |||
|
832 | this.start(options); | |||
|
833 | }, | |||
|
834 | ||||
|
835 | /** @id MochiKit.Visual.Opacity.prototype.update */ | |||
|
836 | update: function (position) { | |||
|
837 | MochiKit.Style.setStyle(this.element, {'opacity': position}); | |||
|
838 | } | |||
|
839 | }); | |||
|
840 | ||||
|
841 | /** @id MochiKit.Visual.Move.prototype */ | |||
|
842 | MochiKit.Visual.Move = function (element, options) { | |||
|
843 | var cls = arguments.callee; | |||
|
844 | if (!(this instanceof cls)) { | |||
|
845 | return new cls(element, options); | |||
|
846 | } | |||
|
847 | this.__init__(element, options); | |||
|
848 | }; | |||
|
849 | ||||
|
850 | MochiKit.Visual.Move.prototype = new MochiKit.Visual.Base(); | |||
|
851 | ||||
|
852 | MochiKit.Base.update(MochiKit.Visual.Move.prototype, { | |||
|
853 | /*** | |||
|
854 | ||||
|
855 | Move an element between its current position to a defined position | |||
|
856 | ||||
|
857 | @param options: 'x' and 'y' for final positions, default to 0, 0. | |||
|
858 | ||||
|
859 | ***/ | |||
|
860 | ||||
|
861 | __class__ : MochiKit.Visual.Move, | |||
|
862 | ||||
|
863 | __init__: function (element, /* optional */options) { | |||
|
864 | this.element = MochiKit.DOM.getElement(element); | |||
|
865 | options = MochiKit.Base.update({ | |||
|
866 | x: 0, | |||
|
867 | y: 0, | |||
|
868 | mode: 'relative' | |||
|
869 | }, options); | |||
|
870 | this.start(options); | |||
|
871 | }, | |||
|
872 | ||||
|
873 | /** @id MochiKit.Visual.Move.prototype.setup */ | |||
|
874 | setup: function () { | |||
|
875 | // Bug in Opera: Opera returns the 'real' position of a static element | |||
|
876 | // or relative element that does not have top/left explicitly set. | |||
|
877 | // ==> Always set top and left for position relative elements in your | |||
|
878 | // stylesheets (to 0 if you do not need them) | |||
|
879 | MochiKit.DOM.makePositioned(this.element); | |||
|
880 | ||||
|
881 | var s = this.element.style; | |||
|
882 | var originalVisibility = s.visibility; | |||
|
883 | var originalDisplay = s.display; | |||
|
884 | if (originalDisplay == 'none') { | |||
|
885 | s.visibility = 'hidden'; | |||
|
886 | s.display = ''; | |||
|
887 | } | |||
|
888 | ||||
|
889 | this.originalLeft = parseFloat(MochiKit.Style.getStyle(this.element, 'left') || '0'); | |||
|
890 | this.originalTop = parseFloat(MochiKit.Style.getStyle(this.element, 'top') || '0'); | |||
|
891 | ||||
|
892 | if (this.options.mode == 'absolute') { | |||
|
893 | // absolute movement, so we need to calc deltaX and deltaY | |||
|
894 | this.options.x -= this.originalLeft; | |||
|
895 | this.options.y -= this.originalTop; | |||
|
896 | } | |||
|
897 | if (originalDisplay == 'none') { | |||
|
898 | s.visibility = originalVisibility; | |||
|
899 | s.display = originalDisplay; | |||
|
900 | } | |||
|
901 | }, | |||
|
902 | ||||
|
903 | /** @id MochiKit.Visual.Move.prototype.update */ | |||
|
904 | update: function (position) { | |||
|
905 | MochiKit.Style.setStyle(this.element, { | |||
|
906 | left: Math.round(this.options.x * position + this.originalLeft) + 'px', | |||
|
907 | top: Math.round(this.options.y * position + this.originalTop) + 'px' | |||
|
908 | }); | |||
|
909 | } | |||
|
910 | }); | |||
|
911 | ||||
|
912 | /** @id MochiKit.Visual.Scale */ | |||
|
913 | MochiKit.Visual.Scale = function (element, percent, options) { | |||
|
914 | var cls = arguments.callee; | |||
|
915 | if (!(this instanceof cls)) { | |||
|
916 | return new cls(element, percent, options); | |||
|
917 | } | |||
|
918 | this.__init__(element, percent, options); | |||
|
919 | }; | |||
|
920 | ||||
|
921 | MochiKit.Visual.Scale.prototype = new MochiKit.Visual.Base(); | |||
|
922 | ||||
|
923 | MochiKit.Base.update(MochiKit.Visual.Scale.prototype, { | |||
|
924 | /*** | |||
|
925 | ||||
|
926 | Change the size of an element. | |||
|
927 | ||||
|
928 | @param percent: final_size = percent*original_size | |||
|
929 | ||||
|
930 | @param options: several options changing scale behaviour | |||
|
931 | ||||
|
932 | ***/ | |||
|
933 | ||||
|
934 | __class__ : MochiKit.Visual.Scale, | |||
|
935 | ||||
|
936 | __init__: function (element, percent, /* optional */options) { | |||
|
937 | this.element = MochiKit.DOM.getElement(element); | |||
|
938 | options = MochiKit.Base.update({ | |||
|
939 | scaleX: true, | |||
|
940 | scaleY: true, | |||
|
941 | scaleContent: true, | |||
|
942 | scaleFromCenter: false, | |||
|
943 | scaleMode: 'box', // 'box' or 'contents' or {} with provided values | |||
|
944 | scaleFrom: 100.0, | |||
|
945 | scaleTo: percent | |||
|
946 | }, options); | |||
|
947 | this.start(options); | |||
|
948 | }, | |||
|
949 | ||||
|
950 | /** @id MochiKit.Visual.Scale.prototype.setup */ | |||
|
951 | setup: function () { | |||
|
952 | this.restoreAfterFinish = this.options.restoreAfterFinish || false; | |||
|
953 | this.elementPositioning = MochiKit.Style.getStyle(this.element, | |||
|
954 | 'position'); | |||
|
955 | ||||
|
956 | var ma = MochiKit.Base.map; | |||
|
957 | var b = MochiKit.Base.bind; | |||
|
958 | this.originalStyle = {}; | |||
|
959 | ma(b(function (k) { | |||
|
960 | this.originalStyle[k] = this.element.style[k]; | |||
|
961 | }, this), ['top', 'left', 'width', 'height', 'fontSize']); | |||
|
962 | ||||
|
963 | this.originalTop = this.element.offsetTop; | |||
|
964 | this.originalLeft = this.element.offsetLeft; | |||
|
965 | ||||
|
966 | var fontSize = MochiKit.Style.getStyle(this.element, | |||
|
967 | 'font-size') || '100%'; | |||
|
968 | ma(b(function (fontSizeType) { | |||
|
969 | if (fontSize.indexOf(fontSizeType) > 0) { | |||
|
970 | this.fontSize = parseFloat(fontSize); | |||
|
971 | this.fontSizeType = fontSizeType; | |||
|
972 | } | |||
|
973 | }, this), ['em', 'px', '%']); | |||
|
974 | ||||
|
975 | this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; | |||
|
976 | ||||
|
977 | if (/^content/.test(this.options.scaleMode)) { | |||
|
978 | this.dims = [this.element.scrollHeight, this.element.scrollWidth]; | |||
|
979 | } else if (this.options.scaleMode == 'box') { | |||
|
980 | this.dims = [this.element.offsetHeight, this.element.offsetWidth]; | |||
|
981 | } else { | |||
|
982 | this.dims = [this.options.scaleMode.originalHeight, | |||
|
983 | this.options.scaleMode.originalWidth]; | |||
|
984 | } | |||
|
985 | }, | |||
|
986 | ||||
|
987 | /** @id MochiKit.Visual.Scale.prototype.update */ | |||
|
988 | update: function (position) { | |||
|
989 | var currentScale = (this.options.scaleFrom/100.0) + | |||
|
990 | (this.factor * position); | |||
|
991 | if (this.options.scaleContent && this.fontSize) { | |||
|
992 | MochiKit.Style.setStyle(this.element, { | |||
|
993 | fontSize: this.fontSize * currentScale + this.fontSizeType | |||
|
994 | }); | |||
|
995 | } | |||
|
996 | this.setDimensions(this.dims[0] * currentScale, | |||
|
997 | this.dims[1] * currentScale); | |||
|
998 | }, | |||
|
999 | ||||
|
1000 | /** @id MochiKit.Visual.Scale.prototype.finish */ | |||
|
1001 | finish: function () { | |||
|
1002 | if (this.restoreAfterFinish) { | |||
|
1003 | MochiKit.Style.setStyle(this.element, this.originalStyle); | |||
|
1004 | } | |||
|
1005 | }, | |||
|
1006 | ||||
|
1007 | /** @id MochiKit.Visual.Scale.prototype.setDimensions */ | |||
|
1008 | setDimensions: function (height, width) { | |||
|
1009 | var d = {}; | |||
|
1010 | var r = Math.round; | |||
|
1011 | if (/MSIE/.test(navigator.userAgent)) { | |||
|
1012 | r = Math.ceil; | |||
|
1013 | } | |||
|
1014 | if (this.options.scaleX) { | |||
|
1015 | d.width = r(width) + 'px'; | |||
|
1016 | } | |||
|
1017 | if (this.options.scaleY) { | |||
|
1018 | d.height = r(height) + 'px'; | |||
|
1019 | } | |||
|
1020 | if (this.options.scaleFromCenter) { | |||
|
1021 | var topd = (height - this.dims[0])/2; | |||
|
1022 | var leftd = (width - this.dims[1])/2; | |||
|
1023 | if (this.elementPositioning == 'absolute') { | |||
|
1024 | if (this.options.scaleY) { | |||
|
1025 | d.top = this.originalTop - topd + 'px'; | |||
|
1026 | } | |||
|
1027 | if (this.options.scaleX) { | |||
|
1028 | d.left = this.originalLeft - leftd + 'px'; | |||
|
1029 | } | |||
|
1030 | } else { | |||
|
1031 | if (this.options.scaleY) { | |||
|
1032 | d.top = -topd + 'px'; | |||
|
1033 | } | |||
|
1034 | if (this.options.scaleX) { | |||
|
1035 | d.left = -leftd + 'px'; | |||
|
1036 | } | |||
|
1037 | } | |||
|
1038 | } | |||
|
1039 | MochiKit.Style.setStyle(this.element, d); | |||
|
1040 | } | |||
|
1041 | }); | |||
|
1042 | ||||
|
1043 | /** @id MochiKit.Visual.Highlight */ | |||
|
1044 | MochiKit.Visual.Highlight = function (element, options) { | |||
|
1045 | var cls = arguments.callee; | |||
|
1046 | if (!(this instanceof cls)) { | |||
|
1047 | return new cls(element, options); | |||
|
1048 | } | |||
|
1049 | this.__init__(element, options); | |||
|
1050 | }; | |||
|
1051 | ||||
|
1052 | MochiKit.Visual.Highlight.prototype = new MochiKit.Visual.Base(); | |||
|
1053 | ||||
|
1054 | MochiKit.Base.update(MochiKit.Visual.Highlight.prototype, { | |||
|
1055 | /*** | |||
|
1056 | ||||
|
1057 | Highlight an item of the page. | |||
|
1058 | ||||
|
1059 | @param options: 'startcolor' for choosing highlighting color, default | |||
|
1060 | to '#ffff99'. | |||
|
1061 | ||||
|
1062 | ***/ | |||
|
1063 | ||||
|
1064 | __class__ : MochiKit.Visual.Highlight, | |||
|
1065 | ||||
|
1066 | __init__: function (element, /* optional */options) { | |||
|
1067 | this.element = MochiKit.DOM.getElement(element); | |||
|
1068 | options = MochiKit.Base.update({ | |||
|
1069 | startcolor: '#ffff99' | |||
|
1070 | }, options); | |||
|
1071 | this.start(options); | |||
|
1072 | }, | |||
|
1073 | ||||
|
1074 | /** @id MochiKit.Visual.Highlight.prototype.setup */ | |||
|
1075 | setup: function () { | |||
|
1076 | var b = MochiKit.Base; | |||
|
1077 | var s = MochiKit.Style; | |||
|
1078 | // Prevent executing on elements not in the layout flow | |||
|
1079 | if (s.getStyle(this.element, 'display') == 'none') { | |||
|
1080 | this.cancel(); | |||
|
1081 | return; | |||
|
1082 | } | |||
|
1083 | // Disable background image during the effect | |||
|
1084 | this.oldStyle = { | |||
|
1085 | backgroundImage: s.getStyle(this.element, 'background-image') | |||
|
1086 | }; | |||
|
1087 | s.setStyle(this.element, { | |||
|
1088 | backgroundImage: 'none' | |||
|
1089 | }); | |||
|
1090 | ||||
|
1091 | if (!this.options.endcolor) { | |||
|
1092 | this.options.endcolor = | |||
|
1093 | MochiKit.Color.Color.fromBackground(this.element).toHexString(); | |||
|
1094 | } | |||
|
1095 | if (b.isUndefinedOrNull(this.options.restorecolor)) { | |||
|
1096 | this.options.restorecolor = s.getStyle(this.element, | |||
|
1097 | 'background-color'); | |||
|
1098 | } | |||
|
1099 | // init color calculations | |||
|
1100 | this._base = b.map(b.bind(function (i) { | |||
|
1101 | return parseInt( | |||
|
1102 | this.options.startcolor.slice(i*2 + 1, i*2 + 3), 16); | |||
|
1103 | }, this), [0, 1, 2]); | |||
|
1104 | this._delta = b.map(b.bind(function (i) { | |||
|
1105 | return parseInt(this.options.endcolor.slice(i*2 + 1, i*2 + 3), 16) | |||
|
1106 | - this._base[i]; | |||
|
1107 | }, this), [0, 1, 2]); | |||
|
1108 | }, | |||
|
1109 | ||||
|
1110 | /** @id MochiKit.Visual.Highlight.prototype.update */ | |||
|
1111 | update: function (position) { | |||
|
1112 | var m = '#'; | |||
|
1113 | MochiKit.Base.map(MochiKit.Base.bind(function (i) { | |||
|
1114 | m += MochiKit.Color.toColorPart(Math.round(this._base[i] + | |||
|
1115 | this._delta[i]*position)); | |||
|
1116 | }, this), [0, 1, 2]); | |||
|
1117 | MochiKit.Style.setStyle(this.element, { | |||
|
1118 | backgroundColor: m | |||
|
1119 | }); | |||
|
1120 | }, | |||
|
1121 | ||||
|
1122 | /** @id MochiKit.Visual.Highlight.prototype.finish */ | |||
|
1123 | finish: function () { | |||
|
1124 | MochiKit.Style.setStyle(this.element, | |||
|
1125 | MochiKit.Base.update(this.oldStyle, { | |||
|
1126 | backgroundColor: this.options.restorecolor | |||
|
1127 | })); | |||
|
1128 | } | |||
|
1129 | }); | |||
|
1130 | ||||
|
1131 | /** @id MochiKit.Visual.ScrollTo */ | |||
|
1132 | MochiKit.Visual.ScrollTo = function (element, options) { | |||
|
1133 | var cls = arguments.callee; | |||
|
1134 | if (!(this instanceof cls)) { | |||
|
1135 | return new cls(element, options); | |||
|
1136 | } | |||
|
1137 | this.__init__(element, options); | |||
|
1138 | }; | |||
|
1139 | ||||
|
1140 | MochiKit.Visual.ScrollTo.prototype = new MochiKit.Visual.Base(); | |||
|
1141 | ||||
|
1142 | MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype, { | |||
|
1143 | /*** | |||
|
1144 | ||||
|
1145 | Scroll to an element in the page. | |||
|
1146 | ||||
|
1147 | ***/ | |||
|
1148 | ||||
|
1149 | __class__ : MochiKit.Visual.ScrollTo, | |||
|
1150 | ||||
|
1151 | __init__: function (element, /* optional */options) { | |||
|
1152 | this.element = MochiKit.DOM.getElement(element); | |||
|
1153 | this.start(options); | |||
|
1154 | }, | |||
|
1155 | ||||
|
1156 | /** @id MochiKit.Visual.ScrollTo.prototype.setup */ | |||
|
1157 | setup: function () { | |||
|
1158 | var p = MochiKit.Position; | |||
|
1159 | p.prepare(); | |||
|
1160 | var offsets = p.cumulativeOffset(this.element); | |||
|
1161 | if (this.options.offset) { | |||
|
1162 | offsets.y += this.options.offset; | |||
|
1163 | } | |||
|
1164 | var max; | |||
|
1165 | if (window.innerHeight) { | |||
|
1166 | max = window.innerHeight - window.height; | |||
|
1167 | } else if (document.documentElement && | |||
|
1168 | document.documentElement.clientHeight) { | |||
|
1169 | max = document.documentElement.clientHeight - | |||
|
1170 | document.body.scrollHeight; | |||
|
1171 | } else if (document.body) { | |||
|
1172 | max = document.body.clientHeight - document.body.scrollHeight; | |||
|
1173 | } | |||
|
1174 | this.scrollStart = p.windowOffset.y; | |||
|
1175 | this.delta = (offsets.y > max ? max : offsets.y) - this.scrollStart; | |||
|
1176 | }, | |||
|
1177 | ||||
|
1178 | /** @id MochiKit.Visual.ScrollTo.prototype.update */ | |||
|
1179 | update: function (position) { | |||
|
1180 | var p = MochiKit.Position; | |||
|
1181 | p.prepare(); | |||
|
1182 | window.scrollTo(p.windowOffset.x, this.scrollStart + (position * this.delta)); | |||
|
1183 | } | |||
|
1184 | }); | |||
|
1185 | ||||
|
1186 | MochiKit.Visual.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; | |||
|
1187 | ||||
|
1188 | MochiKit.Visual.Morph = function (element, options) { | |||
|
1189 | var cls = arguments.callee; | |||
|
1190 | if (!(this instanceof cls)) { | |||
|
1191 | return new cls(element, options); | |||
|
1192 | } | |||
|
1193 | this.__init__(element, options); | |||
|
1194 | }; | |||
|
1195 | ||||
|
1196 | MochiKit.Visual.Morph.prototype = new MochiKit.Visual.Base(); | |||
|
1197 | ||||
|
1198 | MochiKit.Base.update(MochiKit.Visual.Morph.prototype, { | |||
|
1199 | /*** | |||
|
1200 | ||||
|
1201 | Morph effect: make a transformation from current style to the given style, | |||
|
1202 | automatically making a transition between the two. | |||
|
1203 | ||||
|
1204 | ***/ | |||
|
1205 | ||||
|
1206 | __class__ : MochiKit.Visual.Morph, | |||
|
1207 | ||||
|
1208 | __init__: function (element, /* optional */options) { | |||
|
1209 | this.element = MochiKit.DOM.getElement(element); | |||
|
1210 | this.start(options); | |||
|
1211 | }, | |||
|
1212 | ||||
|
1213 | /** @id MochiKit.Visual.Morph.prototype.setup */ | |||
|
1214 | setup: function () { | |||
|
1215 | var b = MochiKit.Base; | |||
|
1216 | var style = this.options.style; | |||
|
1217 | this.styleStart = {}; | |||
|
1218 | this.styleEnd = {}; | |||
|
1219 | this.units = {}; | |||
|
1220 | var value, unit; | |||
|
1221 | for (var s in style) { | |||
|
1222 | value = style[s]; | |||
|
1223 | s = b.camelize(s); | |||
|
1224 | if (MochiKit.Visual.CSS_LENGTH.test(value)) { | |||
|
1225 | var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); | |||
|
1226 | value = parseFloat(components[1]); | |||
|
1227 | unit = (components.length == 3) ? components[2] : null; | |||
|
1228 | this.styleEnd[s] = value; | |||
|
1229 | this.units[s] = unit; | |||
|
1230 | value = MochiKit.Style.getStyle(this.element, s); | |||
|
1231 | components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); | |||
|
1232 | value = parseFloat(components[1]); | |||
|
1233 | this.styleStart[s] = value; | |||
|
1234 | } else { | |||
|
1235 | var c = MochiKit.Color.Color; | |||
|
1236 | value = c.fromString(value); | |||
|
1237 | if (value) { | |||
|
1238 | this.units[s] = "color"; | |||
|
1239 | this.styleEnd[s] = value.toHexString(); | |||
|
1240 | value = MochiKit.Style.getStyle(this.element, s); | |||
|
1241 | this.styleStart[s] = c.fromString(value).toHexString(); | |||
|
1242 | ||||
|
1243 | this.styleStart[s] = b.map(b.bind(function (i) { | |||
|
1244 | return parseInt( | |||
|
1245 | this.styleStart[s].slice(i*2 + 1, i*2 + 3), 16); | |||
|
1246 | }, this), [0, 1, 2]); | |||
|
1247 | this.styleEnd[s] = b.map(b.bind(function (i) { | |||
|
1248 | return parseInt( | |||
|
1249 | this.styleEnd[s].slice(i*2 + 1, i*2 + 3), 16); | |||
|
1250 | }, this), [0, 1, 2]); | |||
|
1251 | } | |||
|
1252 | } | |||
|
1253 | } | |||
|
1254 | }, | |||
|
1255 | ||||
|
1256 | /** @id MochiKit.Visual.Morph.prototype.update */ | |||
|
1257 | update: function (position) { | |||
|
1258 | var value; | |||
|
1259 | for (var s in this.styleStart) { | |||
|
1260 | if (this.units[s] == "color") { | |||
|
1261 | var m = '#'; | |||
|
1262 | var start = this.styleStart[s]; | |||
|
1263 | var end = this.styleEnd[s]; | |||
|
1264 | MochiKit.Base.map(MochiKit.Base.bind(function (i) { | |||
|
1265 | m += MochiKit.Color.toColorPart(Math.round(start[i] + | |||
|
1266 | (end[i] - start[i])*position)); | |||
|
1267 | }, this), [0, 1, 2]); | |||
|
1268 | this.element.style[s] = m; | |||
|
1269 | } else { | |||
|
1270 | value = this.styleStart[s] + Math.round((this.styleEnd[s] - this.styleStart[s]) * position * 1000) / 1000 + this.units[s]; | |||
|
1271 | this.element.style[s] = value; | |||
|
1272 | } | |||
|
1273 | } | |||
|
1274 | } | |||
|
1275 | }); | |||
|
1276 | ||||
|
1277 | /*** | |||
|
1278 | ||||
|
1279 | Combination effects. | |||
|
1280 | ||||
|
1281 | ***/ | |||
|
1282 | ||||
|
1283 | /** @id MochiKit.Visual.fade */ | |||
|
1284 | MochiKit.Visual.fade = function (element, /* optional */ options) { | |||
|
1285 | /*** | |||
|
1286 | ||||
|
1287 | Fade a given element: change its opacity and hide it in the end. | |||
|
1288 | ||||
|
1289 | @param options: 'to' and 'from' to change opacity. | |||
|
1290 | ||||
|
1291 | ***/ | |||
|
1292 | var s = MochiKit.Style; | |||
|
1293 | var oldOpacity = s.getStyle(element, 'opacity'); | |||
|
1294 | options = MochiKit.Base.update({ | |||
|
1295 | from: s.getStyle(element, 'opacity') || 1.0, | |||
|
1296 | to: 0.0, | |||
|
1297 | afterFinishInternal: function (effect) { | |||
|
1298 | if (effect.options.to !== 0) { | |||
|
1299 | return; | |||
|
1300 | } | |||
|
1301 | s.hideElement(effect.element); | |||
|
1302 | s.setStyle(effect.element, {'opacity': oldOpacity}); | |||
|
1303 | } | |||
|
1304 | }, options); | |||
|
1305 | return new MochiKit.Visual.Opacity(element, options); | |||
|
1306 | }; | |||
|
1307 | ||||
|
1308 | /** @id MochiKit.Visual.appear */ | |||
|
1309 | MochiKit.Visual.appear = function (element, /* optional */ options) { | |||
|
1310 | /*** | |||
|
1311 | ||||
|
1312 | Make an element appear. | |||
|
1313 | ||||
|
1314 | @param options: 'to' and 'from' to change opacity. | |||
|
1315 | ||||
|
1316 | ***/ | |||
|
1317 | var s = MochiKit.Style; | |||
|
1318 | var v = MochiKit.Visual; | |||
|
1319 | options = MochiKit.Base.update({ | |||
|
1320 | from: (s.getStyle(element, 'display') == 'none' ? 0.0 : | |||
|
1321 | s.getStyle(element, 'opacity') || 0.0), | |||
|
1322 | to: 1.0, | |||
|
1323 | // force Safari to render floated elements properly | |||
|
1324 | afterFinishInternal: function (effect) { | |||
|
1325 | v.forceRerendering(effect.element); | |||
|
1326 | }, | |||
|
1327 | beforeSetupInternal: function (effect) { | |||
|
1328 | s.setStyle(effect.element, {'opacity': effect.options.from}); | |||
|
1329 | s.showElement(effect.element); | |||
|
1330 | } | |||
|
1331 | }, options); | |||
|
1332 | return new v.Opacity(element, options); | |||
|
1333 | }; | |||
|
1334 | ||||
|
1335 | /** @id MochiKit.Visual.puff */ | |||
|
1336 | MochiKit.Visual.puff = function (element, /* optional */ options) { | |||
|
1337 | /*** | |||
|
1338 | ||||
|
1339 | 'Puff' an element: grow it to double size, fading it and make it hidden. | |||
|
1340 | ||||
|
1341 | ***/ | |||
|
1342 | var s = MochiKit.Style; | |||
|
1343 | var v = MochiKit.Visual; | |||
|
1344 | element = MochiKit.DOM.getElement(element); | |||
|
1345 | var oldStyle = { | |||
|
1346 | position: s.getStyle(element, 'position'), | |||
|
1347 | top: element.style.top, | |||
|
1348 | left: element.style.left, | |||
|
1349 | width: element.style.width, | |||
|
1350 | height: element.style.height, | |||
|
1351 | opacity: s.getStyle(element, 'opacity') | |||
|
1352 | }; | |||
|
1353 | options = MochiKit.Base.update({ | |||
|
1354 | beforeSetupInternal: function (effect) { | |||
|
1355 | MochiKit.Position.absolutize(effect.effects[0].element); | |||
|
1356 | }, | |||
|
1357 | afterFinishInternal: function (effect) { | |||
|
1358 | s.hideElement(effect.effects[0].element); | |||
|
1359 | s.setStyle(effect.effects[0].element, oldStyle); | |||
|
1360 | }, | |||
|
1361 | scaleContent: true, | |||
|
1362 | scaleFromCenter: true | |||
|
1363 | }, options); | |||
|
1364 | return new v.Parallel( | |||
|
1365 | [new v.Scale(element, 200, | |||
|
1366 | {sync: true, scaleFromCenter: options.scaleFromCenter, | |||
|
1367 | scaleContent: options.scaleContent, restoreAfterFinish: true}), | |||
|
1368 | new v.Opacity(element, {sync: true, to: 0.0 })], | |||
|
1369 | options); | |||
|
1370 | }; | |||
|
1371 | ||||
|
1372 | /** @id MochiKit.Visual.blindUp */ | |||
|
1373 | MochiKit.Visual.blindUp = function (element, /* optional */ options) { | |||
|
1374 | /*** | |||
|
1375 | ||||
|
1376 | Blind an element up: change its vertical size to 0. | |||
|
1377 | ||||
|
1378 | ***/ | |||
|
1379 | var d = MochiKit.DOM; | |||
|
1380 | element = d.getElement(element); | |||
|
1381 | var elemClip = d.makeClipping(element); | |||
|
1382 | options = MochiKit.Base.update({ | |||
|
1383 | scaleContent: false, | |||
|
1384 | scaleX: false, | |||
|
1385 | restoreAfterFinish: true, | |||
|
1386 | afterFinishInternal: function (effect) { | |||
|
1387 | MochiKit.Style.hideElement(effect.element); | |||
|
1388 | d.undoClipping(effect.element, elemClip); | |||
|
1389 | } | |||
|
1390 | }, options); | |||
|
1391 | ||||
|
1392 | return new MochiKit.Visual.Scale(element, 0, options); | |||
|
1393 | }; | |||
|
1394 | ||||
|
1395 | /** @id MochiKit.Visual.blindDown */ | |||
|
1396 | MochiKit.Visual.blindDown = function (element, /* optional */ options) { | |||
|
1397 | /*** | |||
|
1398 | ||||
|
1399 | Blind an element down: restore its vertical size. | |||
|
1400 | ||||
|
1401 | ***/ | |||
|
1402 | var d = MochiKit.DOM; | |||
|
1403 | var s = MochiKit.Style; | |||
|
1404 | element = d.getElement(element); | |||
|
1405 | var elementDimensions = s.getElementDimensions(element); | |||
|
1406 | var elemClip; | |||
|
1407 | options = MochiKit.Base.update({ | |||
|
1408 | scaleContent: false, | |||
|
1409 | scaleX: false, | |||
|
1410 | scaleFrom: 0, | |||
|
1411 | scaleMode: {originalHeight: elementDimensions.h, | |||
|
1412 | originalWidth: elementDimensions.w}, | |||
|
1413 | restoreAfterFinish: true, | |||
|
1414 | afterSetupInternal: function (effect) { | |||
|
1415 | elemClip = d.makeClipping(effect.element); | |||
|
1416 | s.setStyle(effect.element, {height: '0px'}); | |||
|
1417 | s.showElement(effect.element); | |||
|
1418 | }, | |||
|
1419 | afterFinishInternal: function (effect) { | |||
|
1420 | d.undoClipping(effect.element, elemClip); | |||
|
1421 | } | |||
|
1422 | }, options); | |||
|
1423 | return new MochiKit.Visual.Scale(element, 100, options); | |||
|
1424 | }; | |||
|
1425 | ||||
|
1426 | /** @id MochiKit.Visual.switchOff */ | |||
|
1427 | MochiKit.Visual.switchOff = function (element, /* optional */ options) { | |||
|
1428 | /*** | |||
|
1429 | ||||
|
1430 | Apply a switch-off-like effect. | |||
|
1431 | ||||
|
1432 | ***/ | |||
|
1433 | var d = MochiKit.DOM; | |||
|
1434 | element = d.getElement(element); | |||
|
1435 | var oldOpacity = MochiKit.Style.getStyle(element, 'opacity'); | |||
|
1436 | var elemClip; | |||
|
1437 | options = MochiKit.Base.update({ | |||
|
1438 | duration: 0.3, | |||
|
1439 | scaleFromCenter: true, | |||
|
1440 | scaleX: false, | |||
|
1441 | scaleContent: false, | |||
|
1442 | restoreAfterFinish: true, | |||
|
1443 | beforeSetupInternal: function (effect) { | |||
|
1444 | d.makePositioned(effect.element); | |||
|
1445 | elemClip = d.makeClipping(effect.element); | |||
|
1446 | }, | |||
|
1447 | afterFinishInternal: function (effect) { | |||
|
1448 | MochiKit.Style.hideElement(effect.element); | |||
|
1449 | d.undoClipping(effect.element, elemClip); | |||
|
1450 | d.undoPositioned(effect.element); | |||
|
1451 | MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity}); | |||
|
1452 | } | |||
|
1453 | }, options); | |||
|
1454 | var v = MochiKit.Visual; | |||
|
1455 | return new v.appear(element, { | |||
|
1456 | duration: 0.4, | |||
|
1457 | from: 0, | |||
|
1458 | transition: v.Transitions.flicker, | |||
|
1459 | afterFinishInternal: function (effect) { | |||
|
1460 | new v.Scale(effect.element, 1, options); | |||
|
1461 | } | |||
|
1462 | }); | |||
|
1463 | }; | |||
|
1464 | ||||
|
1465 | /** @id MochiKit.Visual.dropOut */ | |||
|
1466 | MochiKit.Visual.dropOut = function (element, /* optional */ options) { | |||
|
1467 | /*** | |||
|
1468 | ||||
|
1469 | Make an element fall and disappear. | |||
|
1470 | ||||
|
1471 | ***/ | |||
|
1472 | var d = MochiKit.DOM; | |||
|
1473 | var s = MochiKit.Style; | |||
|
1474 | element = d.getElement(element); | |||
|
1475 | var oldStyle = { | |||
|
1476 | top: s.getStyle(element, 'top'), | |||
|
1477 | left: s.getStyle(element, 'left'), | |||
|
1478 | opacity: s.getStyle(element, 'opacity') | |||
|
1479 | }; | |||
|
1480 | ||||
|
1481 | options = MochiKit.Base.update({ | |||
|
1482 | duration: 0.5, | |||
|
1483 | distance: 100, | |||
|
1484 | beforeSetupInternal: function (effect) { | |||
|
1485 | d.makePositioned(effect.effects[0].element); | |||
|
1486 | }, | |||
|
1487 | afterFinishInternal: function (effect) { | |||
|
1488 | s.hideElement(effect.effects[0].element); | |||
|
1489 | d.undoPositioned(effect.effects[0].element); | |||
|
1490 | s.setStyle(effect.effects[0].element, oldStyle); | |||
|
1491 | } | |||
|
1492 | }, options); | |||
|
1493 | var v = MochiKit.Visual; | |||
|
1494 | return new v.Parallel( | |||
|
1495 | [new v.Move(element, {x: 0, y: options.distance, sync: true}), | |||
|
1496 | new v.Opacity(element, {sync: true, to: 0.0})], | |||
|
1497 | options); | |||
|
1498 | }; | |||
|
1499 | ||||
|
1500 | /** @id MochiKit.Visual.shake */ | |||
|
1501 | MochiKit.Visual.shake = function (element, /* optional */ options) { | |||
|
1502 | /*** | |||
|
1503 | ||||
|
1504 | Move an element from left to right several times. | |||
|
1505 | ||||
|
1506 | ***/ | |||
|
1507 | var d = MochiKit.DOM; | |||
|
1508 | var v = MochiKit.Visual; | |||
|
1509 | var s = MochiKit.Style; | |||
|
1510 | element = d.getElement(element); | |||
|
1511 | options = MochiKit.Base.update({ | |||
|
1512 | x: -20, | |||
|
1513 | y: 0, | |||
|
1514 | duration: 0.05, | |||
|
1515 | afterFinishInternal: function (effect) { | |||
|
1516 | d.undoPositioned(effect.element); | |||
|
1517 | s.setStyle(effect.element, oldStyle); | |||
|
1518 | } | |||
|
1519 | }, options); | |||
|
1520 | var oldStyle = { | |||
|
1521 | top: s.getStyle(element, 'top'), | |||
|
1522 | left: s.getStyle(element, 'left') }; | |||
|
1523 | return new v.Move(element, | |||
|
1524 | {x: 20, y: 0, duration: 0.05, afterFinishInternal: function (effect) { | |||
|
1525 | new v.Move(effect.element, | |||
|
1526 | {x: -40, y: 0, duration: 0.1, afterFinishInternal: function (effect) { | |||
|
1527 | new v.Move(effect.element, | |||
|
1528 | {x: 40, y: 0, duration: 0.1, afterFinishInternal: function (effect) { | |||
|
1529 | new v.Move(effect.element, | |||
|
1530 | {x: -40, y: 0, duration: 0.1, afterFinishInternal: function (effect) { | |||
|
1531 | new v.Move(effect.element, | |||
|
1532 | {x: 40, y: 0, duration: 0.1, afterFinishInternal: function (effect) { | |||
|
1533 | new v.Move(effect.element, options | |||
|
1534 | ) }}) }}) }}) }}) }}); | |||
|
1535 | }; | |||
|
1536 | ||||
|
1537 | /** @id MochiKit.Visual.slideDown */ | |||
|
1538 | MochiKit.Visual.slideDown = function (element, /* optional */ options) { | |||
|
1539 | /*** | |||
|
1540 | ||||
|
1541 | Slide an element down. | |||
|
1542 | It needs to have the content of the element wrapped in a container | |||
|
1543 | element with fixed height. | |||
|
1544 | ||||
|
1545 | ***/ | |||
|
1546 | var d = MochiKit.DOM; | |||
|
1547 | var b = MochiKit.Base; | |||
|
1548 | var s = MochiKit.Style; | |||
|
1549 | element = d.getElement(element); | |||
|
1550 | if (!element.firstChild) { | |||
|
1551 | throw "MochiKit.Visual.slideDown must be used on a element with a child"; | |||
|
1552 | } | |||
|
1553 | d.removeEmptyTextNodes(element); | |||
|
1554 | var oldInnerBottom = s.getStyle(element.firstChild, 'bottom') || 0; | |||
|
1555 | var elementDimensions = s.getElementDimensions(element); | |||
|
1556 | var elemClip; | |||
|
1557 | options = b.update({ | |||
|
1558 | scaleContent: false, | |||
|
1559 | scaleX: false, | |||
|
1560 | scaleFrom: 0, | |||
|
1561 | scaleMode: {originalHeight: elementDimensions.h, | |||
|
1562 | originalWidth: elementDimensions.w}, | |||
|
1563 | restoreAfterFinish: true, | |||
|
1564 | afterSetupInternal: function (effect) { | |||
|
1565 | d.makePositioned(effect.element); | |||
|
1566 | d.makePositioned(effect.element.firstChild); | |||
|
1567 | if (/Opera/.test(navigator.userAgent)) { | |||
|
1568 | s.setStyle(effect.element, {top: ''}); | |||
|
1569 | } | |||
|
1570 | elemClip = d.makeClipping(effect.element); | |||
|
1571 | s.setStyle(effect.element, {height: '0px'}); | |||
|
1572 | s.showElement(effect.element); | |||
|
1573 | }, | |||
|
1574 | afterUpdateInternal: function (effect) { | |||
|
1575 | s.setStyle(effect.element.firstChild, | |||
|
1576 | {bottom: (effect.dims[0] - effect.element.clientHeight) + 'px'}); | |||
|
1577 | }, | |||
|
1578 | afterFinishInternal: function (effect) { | |||
|
1579 | d.undoClipping(effect.element, elemClip); | |||
|
1580 | // IE will crash if child is undoPositioned first | |||
|
1581 | if (/MSIE/.test(navigator.userAgent)) { | |||
|
1582 | d.undoPositioned(effect.element); | |||
|
1583 | d.undoPositioned(effect.element.firstChild); | |||
|
1584 | } else { | |||
|
1585 | d.undoPositioned(effect.element.firstChild); | |||
|
1586 | d.undoPositioned(effect.element); | |||
|
1587 | } | |||
|
1588 | s.setStyle(effect.element.firstChild, | |||
|
1589 | {bottom: oldInnerBottom}); | |||
|
1590 | } | |||
|
1591 | }, options); | |||
|
1592 | ||||
|
1593 | return new MochiKit.Visual.Scale(element, 100, options); | |||
|
1594 | }; | |||
|
1595 | ||||
|
1596 | /** @id MochiKit.Visual.slideUp */ | |||
|
1597 | MochiKit.Visual.slideUp = function (element, /* optional */ options) { | |||
|
1598 | /*** | |||
|
1599 | ||||
|
1600 | Slide an element up. | |||
|
1601 | It needs to have the content of the element wrapped in a container | |||
|
1602 | element with fixed height. | |||
|
1603 | ||||
|
1604 | ***/ | |||
|
1605 | var d = MochiKit.DOM; | |||
|
1606 | var b = MochiKit.Base; | |||
|
1607 | var s = MochiKit.Style; | |||
|
1608 | element = d.getElement(element); | |||
|
1609 | if (!element.firstChild) { | |||
|
1610 | throw "MochiKit.Visual.slideUp must be used on a element with a child"; | |||
|
1611 | } | |||
|
1612 | d.removeEmptyTextNodes(element); | |||
|
1613 | var oldInnerBottom = s.getStyle(element.firstChild, 'bottom'); | |||
|
1614 | var elemClip; | |||
|
1615 | options = b.update({ | |||
|
1616 | scaleContent: false, | |||
|
1617 | scaleX: false, | |||
|
1618 | scaleMode: 'box', | |||
|
1619 | scaleFrom: 100, | |||
|
1620 | restoreAfterFinish: true, | |||
|
1621 | beforeStartInternal: function (effect) { | |||
|
1622 | d.makePositioned(effect.element); | |||
|
1623 | d.makePositioned(effect.element.firstChild); | |||
|
1624 | if (/Opera/.test(navigator.userAgent)) { | |||
|
1625 | s.setStyle(effect.element, {top: ''}); | |||
|
1626 | } | |||
|
1627 | elemClip = d.makeClipping(effect.element); | |||
|
1628 | s.showElement(effect.element); | |||
|
1629 | }, | |||
|
1630 | afterUpdateInternal: function (effect) { | |||
|
1631 | s.setStyle(effect.element.firstChild, | |||
|
1632 | {bottom: (effect.dims[0] - effect.element.clientHeight) + 'px'}); | |||
|
1633 | }, | |||
|
1634 | afterFinishInternal: function (effect) { | |||
|
1635 | s.hideElement(effect.element); | |||
|
1636 | d.undoClipping(effect.element, elemClip); | |||
|
1637 | d.undoPositioned(effect.element.firstChild); | |||
|
1638 | d.undoPositioned(effect.element); | |||
|
1639 | s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); | |||
|
1640 | } | |||
|
1641 | }, options); | |||
|
1642 | return new MochiKit.Visual.Scale(element, 0, options); | |||
|
1643 | }; | |||
|
1644 | ||||
|
1645 | // Bug in opera makes the TD containing this element expand for a instance | |||
|
1646 | // after finish | |||
|
1647 | /** @id MochiKit.Visual.squish */ | |||
|
1648 | MochiKit.Visual.squish = function (element, /* optional */ options) { | |||
|
1649 | /*** | |||
|
1650 | ||||
|
1651 | Reduce an element and make it disappear. | |||
|
1652 | ||||
|
1653 | ***/ | |||
|
1654 | var d = MochiKit.DOM; | |||
|
1655 | var b = MochiKit.Base; | |||
|
1656 | var elemClip; | |||
|
1657 | options = b.update({ | |||
|
1658 | restoreAfterFinish: true, | |||
|
1659 | beforeSetupInternal: function (effect) { | |||
|
1660 | elemClip = d.makeClipping(effect.element); | |||
|
1661 | }, | |||
|
1662 | afterFinishInternal: function (effect) { | |||
|
1663 | MochiKit.Style.hideElement(effect.element); | |||
|
1664 | d.undoClipping(effect.element, elemClip); | |||
|
1665 | } | |||
|
1666 | }, options); | |||
|
1667 | ||||
|
1668 | return new MochiKit.Visual.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, options); | |||
|
1669 | }; | |||
|
1670 | ||||
|
1671 | /** @id MochiKit.Visual.grow */ | |||
|
1672 | MochiKit.Visual.grow = function (element, /* optional */ options) { | |||
|
1673 | /*** | |||
|
1674 | ||||
|
1675 | Grow an element to its original size. Make it zero-sized before | |||
|
1676 | if necessary. | |||
|
1677 | ||||
|
1678 | ***/ | |||
|
1679 | var d = MochiKit.DOM; | |||
|
1680 | var v = MochiKit.Visual; | |||
|
1681 | var s = MochiKit.Style; | |||
|
1682 | element = d.getElement(element); | |||
|
1683 | options = MochiKit.Base.update({ | |||
|
1684 | direction: 'center', | |||
|
1685 | moveTransition: v.Transitions.sinoidal, | |||
|
1686 | scaleTransition: v.Transitions.sinoidal, | |||
|
1687 | opacityTransition: v.Transitions.full, | |||
|
1688 | scaleContent: true, | |||
|
1689 | scaleFromCenter: false | |||
|
1690 | }, options); | |||
|
1691 | var oldStyle = { | |||
|
1692 | top: element.style.top, | |||
|
1693 | left: element.style.left, | |||
|
1694 | height: element.style.height, | |||
|
1695 | width: element.style.width, | |||
|
1696 | opacity: s.getStyle(element, 'opacity') | |||
|
1697 | }; | |||
|
1698 | ||||
|
1699 | var dims = s.getElementDimensions(element); | |||
|
1700 | var initialMoveX, initialMoveY; | |||
|
1701 | var moveX, moveY; | |||
|
1702 | ||||
|
1703 | switch (options.direction) { | |||
|
1704 | case 'top-left': | |||
|
1705 | initialMoveX = initialMoveY = moveX = moveY = 0; | |||
|
1706 | break; | |||
|
1707 | case 'top-right': | |||
|
1708 | initialMoveX = dims.w; | |||
|
1709 | initialMoveY = moveY = 0; | |||
|
1710 | moveX = -dims.w; | |||
|
1711 | break; | |||
|
1712 | case 'bottom-left': | |||
|
1713 | initialMoveX = moveX = 0; | |||
|
1714 | initialMoveY = dims.h; | |||
|
1715 | moveY = -dims.h; | |||
|
1716 | break; | |||
|
1717 | case 'bottom-right': | |||
|
1718 | initialMoveX = dims.w; | |||
|
1719 | initialMoveY = dims.h; | |||
|
1720 | moveX = -dims.w; | |||
|
1721 | moveY = -dims.h; | |||
|
1722 | break; | |||
|
1723 | case 'center': | |||
|
1724 | initialMoveX = dims.w / 2; | |||
|
1725 | initialMoveY = dims.h / 2; | |||
|
1726 | moveX = -dims.w / 2; | |||
|
1727 | moveY = -dims.h / 2; | |||
|
1728 | break; | |||
|
1729 | } | |||
|
1730 | ||||
|
1731 | var optionsParallel = MochiKit.Base.update({ | |||
|
1732 | beforeSetupInternal: function (effect) { | |||
|
1733 | s.setStyle(effect.effects[0].element, {height: '0px'}); | |||
|
1734 | s.showElement(effect.effects[0].element); | |||
|
1735 | }, | |||
|
1736 | afterFinishInternal: function (effect) { | |||
|
1737 | d.undoClipping(effect.effects[0].element); | |||
|
1738 | d.undoPositioned(effect.effects[0].element); | |||
|
1739 | s.setStyle(effect.effects[0].element, oldStyle); | |||
|
1740 | } | |||
|
1741 | }, options); | |||
|
1742 | ||||
|
1743 | return new v.Move(element, { | |||
|
1744 | x: initialMoveX, | |||
|
1745 | y: initialMoveY, | |||
|
1746 | duration: 0.01, | |||
|
1747 | beforeSetupInternal: function (effect) { | |||
|
1748 | s.hideElement(effect.element); | |||
|
1749 | d.makeClipping(effect.element); | |||
|
1750 | d.makePositioned(effect.element); | |||
|
1751 | }, | |||
|
1752 | afterFinishInternal: function (effect) { | |||
|
1753 | new v.Parallel( | |||
|
1754 | [new v.Opacity(effect.element, { | |||
|
1755 | sync: true, to: 1.0, from: 0.0, | |||
|
1756 | transition: options.opacityTransition | |||
|
1757 | }), | |||
|
1758 | new v.Move(effect.element, { | |||
|
1759 | x: moveX, y: moveY, sync: true, | |||
|
1760 | transition: options.moveTransition | |||
|
1761 | }), | |||
|
1762 | new v.Scale(effect.element, 100, { | |||
|
1763 | scaleMode: {originalHeight: dims.h, | |||
|
1764 | originalWidth: dims.w}, | |||
|
1765 | sync: true, | |||
|
1766 | scaleFrom: /Opera/.test(navigator.userAgent) ? 1 : 0, | |||
|
1767 | transition: options.scaleTransition, | |||
|
1768 | scaleContent: options.scaleContent, | |||
|
1769 | scaleFromCenter: options.scaleFromCenter, | |||
|
1770 | restoreAfterFinish: true | |||
|
1771 | }) | |||
|
1772 | ], optionsParallel | |||
|
1773 | ); | |||
|
1774 | } | |||
|
1775 | }); | |||
|
1776 | }; | |||
|
1777 | ||||
|
1778 | /** @id MochiKit.Visual.shrink */ | |||
|
1779 | MochiKit.Visual.shrink = function (element, /* optional */ options) { | |||
|
1780 | /*** | |||
|
1781 | ||||
|
1782 | Shrink an element and make it disappear. | |||
|
1783 | ||||
|
1784 | ***/ | |||
|
1785 | var d = MochiKit.DOM; | |||
|
1786 | var v = MochiKit.Visual; | |||
|
1787 | var s = MochiKit.Style; | |||
|
1788 | element = d.getElement(element); | |||
|
1789 | options = MochiKit.Base.update({ | |||
|
1790 | direction: 'center', | |||
|
1791 | moveTransition: v.Transitions.sinoidal, | |||
|
1792 | scaleTransition: v.Transitions.sinoidal, | |||
|
1793 | opacityTransition: v.Transitions.none, | |||
|
1794 | scaleContent: true, | |||
|
1795 | scaleFromCenter: false | |||
|
1796 | }, options); | |||
|
1797 | var oldStyle = { | |||
|
1798 | top: element.style.top, | |||
|
1799 | left: element.style.left, | |||
|
1800 | height: element.style.height, | |||
|
1801 | width: element.style.width, | |||
|
1802 | opacity: s.getStyle(element, 'opacity') | |||
|
1803 | }; | |||
|
1804 | ||||
|
1805 | var dims = s.getElementDimensions(element); | |||
|
1806 | var moveX, moveY; | |||
|
1807 | ||||
|
1808 | switch (options.direction) { | |||
|
1809 | case 'top-left': | |||
|
1810 | moveX = moveY = 0; | |||
|
1811 | break; | |||
|
1812 | case 'top-right': | |||
|
1813 | moveX = dims.w; | |||
|
1814 | moveY = 0; | |||
|
1815 | break; | |||
|
1816 | case 'bottom-left': | |||
|
1817 | moveX = 0; | |||
|
1818 | moveY = dims.h; | |||
|
1819 | break; | |||
|
1820 | case 'bottom-right': | |||
|
1821 | moveX = dims.w; | |||
|
1822 | moveY = dims.h; | |||
|
1823 | break; | |||
|
1824 | case 'center': | |||
|
1825 | moveX = dims.w / 2; | |||
|
1826 | moveY = dims.h / 2; | |||
|
1827 | break; | |||
|
1828 | } | |||
|
1829 | var elemClip; | |||
|
1830 | ||||
|
1831 | var optionsParallel = MochiKit.Base.update({ | |||
|
1832 | beforeStartInternal: function (effect) { | |||
|
1833 | elemClip = d.makePositioned(effect.effects[0].element); | |||
|
1834 | d.makeClipping(effect.effects[0].element); | |||
|
1835 | }, | |||
|
1836 | afterFinishInternal: function (effect) { | |||
|
1837 | s.hideElement(effect.effects[0].element); | |||
|
1838 | d.undoClipping(effect.effects[0].element, elemClip); | |||
|
1839 | d.undoPositioned(effect.effects[0].element); | |||
|
1840 | s.setStyle(effect.effects[0].element, oldStyle); | |||
|
1841 | } | |||
|
1842 | }, options); | |||
|
1843 | ||||
|
1844 | return new v.Parallel( | |||
|
1845 | [new v.Opacity(element, { | |||
|
1846 | sync: true, to: 0.0, from: 1.0, | |||
|
1847 | transition: options.opacityTransition | |||
|
1848 | }), | |||
|
1849 | new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, { | |||
|
1850 | sync: true, transition: options.scaleTransition, | |||
|
1851 | scaleContent: options.scaleContent, | |||
|
1852 | scaleFromCenter: options.scaleFromCenter, | |||
|
1853 | restoreAfterFinish: true | |||
|
1854 | }), | |||
|
1855 | new v.Move(element, { | |||
|
1856 | x: moveX, y: moveY, sync: true, transition: options.moveTransition | |||
|
1857 | }) | |||
|
1858 | ], optionsParallel | |||
|
1859 | ); | |||
|
1860 | }; | |||
|
1861 | ||||
|
1862 | /** @id MochiKit.Visual.pulsate */ | |||
|
1863 | MochiKit.Visual.pulsate = function (element, /* optional */ options) { | |||
|
1864 | /*** | |||
|
1865 | ||||
|
1866 | Pulse an element between appear/fade. | |||
|
1867 | ||||
|
1868 | ***/ | |||
|
1869 | var d = MochiKit.DOM; | |||
|
1870 | var v = MochiKit.Visual; | |||
|
1871 | var b = MochiKit.Base; | |||
|
1872 | var oldOpacity = MochiKit.Style.getStyle(element, 'opacity'); | |||
|
1873 | options = b.update({ | |||
|
1874 | duration: 3.0, | |||
|
1875 | from: 0, | |||
|
1876 | afterFinishInternal: function (effect) { | |||
|
1877 | MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity}); | |||
|
1878 | } | |||
|
1879 | }, options); | |||
|
1880 | var transition = options.transition || v.Transitions.sinoidal; | |||
|
1881 | var reverser = b.bind(function (pos) { | |||
|
1882 | return transition(1 - v.Transitions.pulse(pos, options.pulses)); | |||
|
1883 | }, transition); | |||
|
1884 | b.bind(reverser, transition); | |||
|
1885 | return new v.Opacity(element, b.update({ | |||
|
1886 | transition: reverser}, options)); | |||
|
1887 | }; | |||
|
1888 | ||||
|
1889 | /** @id MochiKit.Visual.fold */ | |||
|
1890 | MochiKit.Visual.fold = function (element, /* optional */ options) { | |||
|
1891 | /*** | |||
|
1892 | ||||
|
1893 | Fold an element, first vertically, then horizontally. | |||
|
1894 | ||||
|
1895 | ***/ | |||
|
1896 | var d = MochiKit.DOM; | |||
|
1897 | var v = MochiKit.Visual; | |||
|
1898 | var s = MochiKit.Style; | |||
|
1899 | element = d.getElement(element); | |||
|
1900 | var oldStyle = { | |||
|
1901 | top: element.style.top, | |||
|
1902 | left: element.style.left, | |||
|
1903 | width: element.style.width, | |||
|
1904 | height: element.style.height | |||
|
1905 | }; | |||
|
1906 | var elemClip = d.makeClipping(element); | |||
|
1907 | options = MochiKit.Base.update({ | |||
|
1908 | scaleContent: false, | |||
|
1909 | scaleX: false, | |||
|
1910 | afterFinishInternal: function (effect) { | |||
|
1911 | new v.Scale(element, 1, { | |||
|
1912 | scaleContent: false, | |||
|
1913 | scaleY: false, | |||
|
1914 | afterFinishInternal: function (effect) { | |||
|
1915 | s.hideElement(effect.element); | |||
|
1916 | d.undoClipping(effect.element, elemClip); | |||
|
1917 | s.setStyle(effect.element, oldStyle); | |||
|
1918 | } | |||
|
1919 | }); | |||
|
1920 | } | |||
|
1921 | }, options); | |||
|
1922 | return new v.Scale(element, 5, options); | |||
|
1923 | }; | |||
|
1924 | ||||
|
1925 | ||||
|
1926 | // Compatibility with MochiKit 1.0 | |||
|
1927 | MochiKit.Visual.Color = MochiKit.Color.Color; | |||
|
1928 | MochiKit.Visual.getElementsComputedStyle = MochiKit.DOM.computedStyle; | |||
|
1929 | ||||
|
1930 | /* end of Rico adaptation */ | |||
|
1931 | ||||
|
1932 | MochiKit.Visual.__new__ = function () { | |||
|
1933 | var m = MochiKit.Base; | |||
|
1934 | ||||
|
1935 | m.nameFunctions(this); | |||
|
1936 | ||||
|
1937 | this.EXPORT_TAGS = { | |||
|
1938 | ":common": this.EXPORT, | |||
|
1939 | ":all": m.concat(this.EXPORT, this.EXPORT_OK) | |||
|
1940 | }; | |||
|
1941 | ||||
|
1942 | }; | |||
|
1943 | ||||
|
1944 | MochiKit.Visual.EXPORT = [ | |||
|
1945 | "roundElement", | |||
|
1946 | "roundClass", | |||
|
1947 | "tagifyText", | |||
|
1948 | "multiple", | |||
|
1949 | "toggle", | |||
|
1950 | "Parallel", | |||
|
1951 | "Opacity", | |||
|
1952 | "Move", | |||
|
1953 | "Scale", | |||
|
1954 | "Highlight", | |||
|
1955 | "ScrollTo", | |||
|
1956 | "Morph", | |||
|
1957 | "fade", | |||
|
1958 | "appear", | |||
|
1959 | "puff", | |||
|
1960 | "blindUp", | |||
|
1961 | "blindDown", | |||
|
1962 | "switchOff", | |||
|
1963 | "dropOut", | |||
|
1964 | "shake", | |||
|
1965 | "slideDown", | |||
|
1966 | "slideUp", | |||
|
1967 | "squish", | |||
|
1968 | "grow", | |||
|
1969 | "shrink", | |||
|
1970 | "pulsate", | |||
|
1971 | "fold" | |||
|
1972 | ]; | |||
|
1973 | ||||
|
1974 | MochiKit.Visual.EXPORT_OK = [ | |||
|
1975 | "Base", | |||
|
1976 | "PAIRS" | |||
|
1977 | ]; | |||
|
1978 | ||||
|
1979 | MochiKit.Visual.__new__(); | |||
|
1980 | ||||
|
1981 | MochiKit.Base._exportSymbols(this, MochiKit.Visual); |
@@ -0,0 +1,10 b'' | |||||
|
1 | # encoding: utf-8 | |||
|
2 | __docformat__ = "restructuredtext en" | |||
|
3 | #------------------------------------------------------------------------------- | |||
|
4 | # Copyright (C) 2005 Fernando Perez <fperez@colorado.edu> | |||
|
5 | # Brian E Granger <ellisonbg@gmail.com> | |||
|
6 | # Benjamin Ragan-Kelley <benjaminrk@gmail.com> | |||
|
7 | # | |||
|
8 | # Distributed under the terms of the BSD License. The full license is in | |||
|
9 | # the file COPYING, distributed as part of this software. | |||
|
10 | #------------------------------------------------------------------------------- |
@@ -0,0 +1,18 b'' | |||||
|
1 | dojo.kwCompoundRequire({ | |||
|
2 | "common": [ | |||
|
3 | "MochiKit.Base", | |||
|
4 | "MochiKit.Iter", | |||
|
5 | "MochiKit.Logging", | |||
|
6 | "MochiKit.DateTime", | |||
|
7 | "MochiKit.Format", | |||
|
8 | "MochiKit.Async", | |||
|
9 | "MochiKit.DOM", | |||
|
10 | "MochiKit.Style", | |||
|
11 | "MochiKit.LoggingPane", | |||
|
12 | "MochiKit.Color", | |||
|
13 | "MochiKit.Signal", | |||
|
14 | "MochiKit.Position", | |||
|
15 | "MochiKit.Visual" | |||
|
16 | ] | |||
|
17 | }); | |||
|
18 | dojo.provide("MochiKit.*"); |
@@ -0,0 +1,375 b'' | |||||
|
1 | // This is from the MochiKit ajax_tables example | |||
|
2 | /* | |||
|
3 | ||||
|
4 | On page load, the SortableManager: | |||
|
5 | ||||
|
6 | - Rips out all of the elements with the mochi-example class. | |||
|
7 | - Finds the elements with the mochi-template class and saves them for | |||
|
8 | later parsing with "MochiTAL". | |||
|
9 | - Finds the anchor tags with the mochi:dataformat attribute and gives them | |||
|
10 | onclick behvaiors to load new data, using their href as the data source. | |||
|
11 | This makes your XML or JSON look like a normal link to a search engine | |||
|
12 | (or javascript-disabled browser). | |||
|
13 | - Clones the thead element from the table because it will be replaced on each | |||
|
14 | sort. | |||
|
15 | - Sets up a default sort key of "object_name" and queues a load of the json | |||
|
16 | document. | |||
|
17 | ||||
|
18 | ||||
|
19 | On data load, the SortableManager: | |||
|
20 | ||||
|
21 | - Parses the table data from the document (columns list, rows list-of-lists) | |||
|
22 | and turns them into a list of [{column:value, ...}] objects for easy sorting | |||
|
23 | and column order stability. | |||
|
24 | - Chooses the default (or previous) sort state and triggers a sort request | |||
|
25 | ||||
|
26 | ||||
|
27 | On sort request: | |||
|
28 | ||||
|
29 | - Replaces the cloned thead element with a copy of it that has the sort | |||
|
30 | indicator (↑ or ↓) for the most recently sorted column (matched up | |||
|
31 | to the first field in the th's mochi:sortcolumn attribute), and attaches | |||
|
32 | onclick, onmousedown, onmouseover, onmouseout behaviors to them. The second | |||
|
33 | field of mochi:sortcolumn attribute is used to perform a non-string sort. | |||
|
34 | - Performs the sort on the objects list. If the second field of | |||
|
35 | mochi:sortcolumn was not "str", then a custom function is used and the | |||
|
36 | results are stored away in a __sort__ key, which is then used to perform the | |||
|
37 | sort (read: shwartzian transform). | |||
|
38 | - Calls processMochiTAL on the page, which finds the mochi-template sections | |||
|
39 | and then looks for mochi:repeat and mochi:content attributes on them, using | |||
|
40 | the data object. | |||
|
41 | ||||
|
42 | */ | |||
|
43 | ||||
|
44 | processMochiTAL = function (dom, data) { | |||
|
45 | /*** | |||
|
46 | ||||
|
47 | A TAL-esque template attribute language processor, | |||
|
48 | including content replacement and repeat | |||
|
49 | ||||
|
50 | ***/ | |||
|
51 | ||||
|
52 | // nodeType == 1 is an element, we're leaving | |||
|
53 | // text nodes alone. | |||
|
54 | if (dom.nodeType != 1) { | |||
|
55 | return; | |||
|
56 | } | |||
|
57 | var attr; | |||
|
58 | // duplicate this element for each item in the | |||
|
59 | // given list, and then process the duplicated | |||
|
60 | // element again (sans mochi:repeat tag) | |||
|
61 | attr = getAttribute(dom, "mochi:repeat"); | |||
|
62 | if (attr) { | |||
|
63 | dom.removeAttribute("mochi:repeat"); | |||
|
64 | var parent = dom.parentNode; | |||
|
65 | attr = attr.split(" "); | |||
|
66 | var name = attr[0]; | |||
|
67 | var lst = valueForKeyPath(data, attr[1]); | |||
|
68 | if (!lst) { | |||
|
69 | return; | |||
|
70 | } | |||
|
71 | for (var i = 0; i < lst.length; i++) { | |||
|
72 | data[name] = lst[i]; | |||
|
73 | var newDOM = dom.cloneNode(true); | |||
|
74 | processMochiTAL(newDOM, data); | |||
|
75 | parent.insertBefore(newDOM, dom); | |||
|
76 | } | |||
|
77 | parent.removeChild(dom); | |||
|
78 | return; | |||
|
79 | } | |||
|
80 | // do content replacement if there's a mochi:content attribute | |||
|
81 | // on the element | |||
|
82 | attr = getAttribute(dom, "mochi:content"); | |||
|
83 | if (attr) { | |||
|
84 | dom.removeAttribute("mochi:content"); | |||
|
85 | replaceChildNodes(dom, valueForKeyPath(data, attr)); | |||
|
86 | return; | |||
|
87 | } | |||
|
88 | // we make a shallow copy of the current list of child nodes | |||
|
89 | // because it *will* change if there's a mochi:repeat in there! | |||
|
90 | var nodes = list(dom.childNodes); | |||
|
91 | for (var i = 0; i < nodes.length; i++) { | |||
|
92 | processMochiTAL(nodes[i], data); | |||
|
93 | } | |||
|
94 | }; | |||
|
95 | ||||
|
96 | mouseOverFunc = function () { | |||
|
97 | addElementClass(this, "over"); | |||
|
98 | }; | |||
|
99 | ||||
|
100 | mouseOutFunc = function () { | |||
|
101 | removeElementClass(this, "over"); | |||
|
102 | }; | |||
|
103 | ||||
|
104 | ignoreEvent = function (ev) { | |||
|
105 | if (ev && ev.preventDefault) { | |||
|
106 | ev.preventDefault(); | |||
|
107 | ev.stopPropagation(); | |||
|
108 | } else if (typeof(event) != 'undefined') { | |||
|
109 | event.cancelBubble = false; | |||
|
110 | event.returnValue = false; | |||
|
111 | } | |||
|
112 | }; | |||
|
113 | ||||
|
114 | SortTransforms = { | |||
|
115 | "str": operator.identity, | |||
|
116 | "istr": function (s) { return s.toLowerCase(); }, | |||
|
117 | /* "isoDate": isoDate*/ | |||
|
118 | }; | |||
|
119 | ||||
|
120 | getAttribute = function (dom, key) { | |||
|
121 | try { | |||
|
122 | return dom.getAttribute(key); | |||
|
123 | } catch (e) { | |||
|
124 | return null; | |||
|
125 | } | |||
|
126 | }; | |||
|
127 | ||||
|
128 | loadFromDataAnchor = function (ev) { | |||
|
129 | ignoreEvent(ev); | |||
|
130 | var format = this.getAttribute("mochi:dataformat"); | |||
|
131 | var href = this.href; | |||
|
132 | sortableManager.loadFromURL(format, href); | |||
|
133 | }; | |||
|
134 | ||||
|
135 | valueForKeyPath = function (data, keyPath) { | |||
|
136 | var chunks = keyPath.split("."); | |||
|
137 | while (chunks.length && data) { | |||
|
138 | data = data[chunks.shift()]; | |||
|
139 | } | |||
|
140 | return data; | |||
|
141 | }; | |||
|
142 | ||||
|
143 | ||||
|
144 | SortableManager = function () { | |||
|
145 | this.thead = null; | |||
|
146 | this.thead_proto = null; | |||
|
147 | this.tbody = null; | |||
|
148 | this.deferred = null; | |||
|
149 | this.columns = []; | |||
|
150 | this.rows = []; | |||
|
151 | this.templates = []; | |||
|
152 | this.sortState = {}; | |||
|
153 | bindMethods(this); | |||
|
154 | }; | |||
|
155 | ||||
|
156 | SortableManager.prototype = { | |||
|
157 | ||||
|
158 | "initialize": function (prefix, sortkey) { | |||
|
159 | // just rip all mochi-examples out of the DOM | |||
|
160 | var examples = getElementsByTagAndClassName(null, prefix+"-example"); | |||
|
161 | while (examples.length) { | |||
|
162 | swapDOM(examples.pop(), null); | |||
|
163 | } | |||
|
164 | // make a template list | |||
|
165 | var templates = getElementsByTagAndClassName(null, prefix+"-template"); | |||
|
166 | for (var i = 0; i < templates.length; i++) { | |||
|
167 | var template = templates[i]; | |||
|
168 | var proto = template.cloneNode(true); | |||
|
169 | removeElementClass(proto, prefix+"-template"); | |||
|
170 | this.templates.push({ | |||
|
171 | "template": proto, | |||
|
172 | "node": template | |||
|
173 | }); | |||
|
174 | } | |||
|
175 | // set up the data anchors to do loads | |||
|
176 | var anchors = getElementsByTagAndClassName("a", null); | |||
|
177 | for (var i = 0; i < anchors.length; i++) { | |||
|
178 | var node = anchors[i]; | |||
|
179 | var format = getAttribute(node, "mochi:dataformat"); | |||
|
180 | if (format) { | |||
|
181 | node.onclick = loadFromDataAnchor; | |||
|
182 | } | |||
|
183 | } | |||
|
184 | ||||
|
185 | // to find sort columns | |||
|
186 | this.thead = getElementsByTagAndClassName("thead", prefix)[0]; | |||
|
187 | this.thead_proto = this.thead.cloneNode(true); | |||
|
188 | ||||
|
189 | this.sortkey = sortkey; | |||
|
190 | /* this.loadFromURL("json", "objects.json");*/ | |||
|
191 | }, | |||
|
192 | ||||
|
193 | "loadFromURL": function (format, url) { | |||
|
194 | log('loadFromURL', format, url); | |||
|
195 | var d; | |||
|
196 | if (this.deferred) { | |||
|
197 | this.deferred.cancel(); | |||
|
198 | } | |||
|
199 | if (format == "xml") { | |||
|
200 | var d = doXHR(url, { | |||
|
201 | mimeType: 'text/xml', | |||
|
202 | headers: {Accept: 'text/xml'} | |||
|
203 | }); | |||
|
204 | d.addCallback(datatableFromXMLRequest); | |||
|
205 | } else if (format == "json") { | |||
|
206 | d = loadJSONDoc(url); | |||
|
207 | } else { | |||
|
208 | throw new TypeError("format " + repr(format) + " not supported"); | |||
|
209 | } | |||
|
210 | // keep track of the current deferred, so that we can cancel it | |||
|
211 | this.deferred = d; | |||
|
212 | var self = this; | |||
|
213 | // on success or error, remove the current deferred because it has | |||
|
214 | // completed, and pass through the result or error | |||
|
215 | d.addBoth(function (res) { | |||
|
216 | self.deferred = null; | |||
|
217 | log('loadFromURL success'); | |||
|
218 | return res; | |||
|
219 | }); | |||
|
220 | // on success, tag the result with the format used so we can display | |||
|
221 | // it | |||
|
222 | d.addCallback(function (res) { | |||
|
223 | res.format = format; | |||
|
224 | return res; | |||
|
225 | }); | |||
|
226 | // call this.initWithData(data) once it's ready | |||
|
227 | d.addCallback(this.initWithData); | |||
|
228 | // if anything goes wrong, except for a simple cancellation, | |||
|
229 | // then log the error and show the logger | |||
|
230 | d.addErrback(function (err) { | |||
|
231 | if (err instanceof CancelledError) { | |||
|
232 | return; | |||
|
233 | } | |||
|
234 | logError(err); | |||
|
235 | logger.debuggingBookmarklet(); | |||
|
236 | }); | |||
|
237 | return d; | |||
|
238 | }, | |||
|
239 | ||||
|
240 | "initWithData": function (data) { | |||
|
241 | /*** | |||
|
242 | ||||
|
243 | Initialize the SortableManager with a table object | |||
|
244 | ||||
|
245 | ***/ | |||
|
246 | ||||
|
247 | // reformat to [{column:value, ...}, ...] style as the objects key | |||
|
248 | var objects = []; | |||
|
249 | var rows = data.rows; | |||
|
250 | var cols = data.columns; | |||
|
251 | for (var i = 0; i < rows.length; i++) { | |||
|
252 | var row = rows[i]; | |||
|
253 | var object = {}; | |||
|
254 | for (var j = 0; j < cols.length; j++) { | |||
|
255 | object[cols[j]] = row[j]; | |||
|
256 | } | |||
|
257 | objects.push(object); | |||
|
258 | } | |||
|
259 | data.objects = objects; | |||
|
260 | this.data = data; | |||
|
261 | // perform a sort and display based upon the previous sort state, | |||
|
262 | // defaulting to an ascending sort if this is the first sort | |||
|
263 | var order = this.sortState[this.sortkey]; | |||
|
264 | if (typeof(order) == 'undefined') { | |||
|
265 | order = true; | |||
|
266 | } | |||
|
267 | this.drawSortedRows(this.sortkey, order, false); | |||
|
268 | ||||
|
269 | }, | |||
|
270 | ||||
|
271 | "onSortClick": function (name) { | |||
|
272 | /*** | |||
|
273 | ||||
|
274 | Return a sort function for click events | |||
|
275 | ||||
|
276 | ***/ | |||
|
277 | // save ourselves from doing a bind | |||
|
278 | var self = this; | |||
|
279 | // on click, flip the last sort order of that column and sort | |||
|
280 | return function () { | |||
|
281 | log('onSortClick', name); | |||
|
282 | var order = self.sortState[name]; | |||
|
283 | if (typeof(order) == 'undefined') { | |||
|
284 | // if it's never been sorted by this column, sort ascending | |||
|
285 | order = true; | |||
|
286 | } else if (self.sortkey == name) { | |||
|
287 | // if this column was sorted most recently, flip the sort order | |||
|
288 | order = !((typeof(order) == 'undefined') ? false : order); | |||
|
289 | } | |||
|
290 | self.drawSortedRows(name, order, true); | |||
|
291 | }; | |||
|
292 | }, | |||
|
293 | ||||
|
294 | "drawSortedRows": function (key, forward, clicked) { | |||
|
295 | /*** | |||
|
296 | ||||
|
297 | Draw the new sorted table body, and modify the column headers | |||
|
298 | if appropriate | |||
|
299 | ||||
|
300 | ***/ | |||
|
301 | log('drawSortedRows', key, forward); | |||
|
302 | ||||
|
303 | // save it so we can flip next time | |||
|
304 | this.sortState[key] = forward; | |||
|
305 | this.sortkey = key; | |||
|
306 | var sortstyle; | |||
|
307 | ||||
|
308 | // setup the sort columns | |||
|
309 | var thead = this.thead_proto.cloneNode(true); | |||
|
310 | var cols = thead.getElementsByTagName("th"); | |||
|
311 | for (var i = 0; i < cols.length; i++) { | |||
|
312 | var col = cols[i]; | |||
|
313 | var sortinfo = getAttribute(col, "mochi:sortcolumn").split(" "); | |||
|
314 | var sortkey = sortinfo[0]; | |||
|
315 | col.onclick = this.onSortClick(sortkey); | |||
|
316 | col.onmousedown = ignoreEvent; | |||
|
317 | col.onmouseover = mouseOverFunc; | |||
|
318 | col.onmouseout = mouseOutFunc; | |||
|
319 | // if this is the sorted column | |||
|
320 | if (sortkey == key) { | |||
|
321 | sortstyle = sortinfo[1]; | |||
|
322 | // \u2193 is down arrow, \u2191 is up arrow | |||
|
323 | // forward sorts mean the rows get bigger going down | |||
|
324 | var arrow = (forward ? "\u2193" : "\u2191"); | |||
|
325 | // add the character to the column header | |||
|
326 | col.appendChild(SPAN(null, arrow)); | |||
|
327 | if (clicked) { | |||
|
328 | col.onmouseover(); | |||
|
329 | } | |||
|
330 | } | |||
|
331 | } | |||
|
332 | this.thead = swapDOM(this.thead, thead); | |||
|
333 | ||||
|
334 | // apply a sort transform to a temporary column named __sort__, | |||
|
335 | // and do the sort based on that column | |||
|
336 | if (!sortstyle) { | |||
|
337 | sortstyle = "str"; | |||
|
338 | } | |||
|
339 | var sortfunc = SortTransforms[sortstyle]; | |||
|
340 | if (!sortfunc) { | |||
|
341 | throw new TypeError("unsupported sort style " + repr(sortstyle)); | |||
|
342 | } | |||
|
343 | var objects = this.data.objects; | |||
|
344 | for (var i = 0; i < objects.length; i++) { | |||
|
345 | var object = objects[i]; | |||
|
346 | object.__sort__ = sortfunc(object[key]); | |||
|
347 | } | |||
|
348 | ||||
|
349 | // perform the sort based on the state given (forward or reverse) | |||
|
350 | var cmp = (forward ? keyComparator : reverseKeyComparator); | |||
|
351 | objects.sort(cmp("__sort__")); | |||
|
352 | ||||
|
353 | // process every template with the given data | |||
|
354 | // and put the processed templates in the DOM | |||
|
355 | for (var i = 0; i < this.templates.length; i++) { | |||
|
356 | log('template', i, template); | |||
|
357 | var template = this.templates[i]; | |||
|
358 | var dom = template.template.cloneNode(true); | |||
|
359 | processMochiTAL(dom, this.data); | |||
|
360 | template.node = swapDOM(template.node, dom); | |||
|
361 | } | |||
|
362 | //permission based coloring | |||
|
363 | ||||
|
364 | ||||
|
365 | ||||
|
366 | } | |||
|
367 | ||||
|
368 | }; | |||
|
369 | ||||
|
370 | // create the global SortableManager and initialize it on page load | |||
|
371 | sortableManager = new SortableManager(); | |||
|
372 | sortableManager2 = new SortableManager(); | |||
|
373 | ||||
|
374 | addLoadEvent(function() {sortableManager.initialize("notebook", "dateModified")}); | |||
|
375 | addLoadEvent(function() {sortableManager2.initialize("user", "username")}); |
@@ -0,0 +1,14 b'' | |||||
|
1 | =================== | |||
|
2 | External Packages | |||
|
3 | =================== | |||
|
4 | ||||
|
5 | This directory contains external packages which we ship inside IPython for ease | |||
|
6 | of distributions for users. | |||
|
7 | ||||
|
8 | Currently we include: | |||
|
9 | ||||
|
10 | - configobj | |||
|
11 | - Itpl | |||
|
12 | - MochiKit | |||
|
13 | - simplegeneric | |||
|
14 | - validate |
@@ -0,0 +1,16 b'' | |||||
|
1 | # encoding: utf-8 | |||
|
2 | ||||
|
3 | """ | |||
|
4 | This package contains all third-party modules bundled with IPython. | |||
|
5 | """ | |||
|
6 | ||||
|
7 | __docformat__ = "restructuredtext en" | |||
|
8 | ||||
|
9 | #------------------------------------------------------------------------------- | |||
|
10 | # Copyright (C) 2008 The IPython Development Team | |||
|
11 | # | |||
|
12 | # Distributed under the terms of the BSD License. The full license is in | |||
|
13 | # the file COPYING, distributed as part of this software. | |||
|
14 | #------------------------------------------------------------------------------- | |||
|
15 | ||||
|
16 | __all__ = ['simplegeneric','twisted','Itpl', 'MochiKit'] |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
General Comments 0
You need to be logged in to leave comments.
Login now