Sed scelerisque sagittis lorem & phasellus sodales. Nulla urna justo, vehicula in, suscipit nec, molestie sed, tellus. Quisque justo. Nam libero leo, elementum in, dapibus a, suscipit vitae, purus. Duis arcu. Integer dignissim fermentum enim. Morbi convallis felis vel nibh. Etiam viverra augue non enim.
13 |
14 |
“Level 1 heading”
15 |
Sed scelerisque sagittis lorem. Phasellus sodales. Nulla urna justo, vehicula in, suscipit nec, molestie sed, tellus. Quisque justo. Nam libero leo, elementum in, dapibus a, suscipit vitae, purus. Duis arcu. Integer dignissim fermentum enim. Morbi convallis felis vel nibh. Etiam viverra augue non enim.
16 |
Sed scelerisque sagittis lorem. Phasellus sodales. Nulla urna justo, vehicula in, suscipit nec, molestie sed, tellus. Quisque justo. Nam libero leo, elementum in, dapibus a, suscipit vitae, purus. Duis arcu. Integer dignissim fermentum enim. Morbi convallis felis vel nibh. Etiam viverra augue non enim.
17 |
18 |
Level 02 Heading
19 |
20 |
Sed scelerisque sagittis lorem. Phasellus sodales. Nulla urna justo, vehicula in, suscipit nec, molestie sed, tellus. Quisque justo. Nam libero leo, elementum in, dapibus a, suscipit vitae, purus. Duis arcu. Integer dignissim fermentum enim. Morbi convallis felis vel nibh. Etiam viverra augue non enim.
21 |
Level 03 Heading
22 |
23 |
Sed scelerisque sagittis lorem. Phasellus sodales. Nulla urna justo, vehicula in, suscipit nec, molestie sed, tellus. Quisque justo. Nam libero leo, elementum in, dapibus a, suscipit vitae, purus. Duis arcu. Integer dignissim fermentum enim. Morbi convallis felis vel nibh. Etiam viverra augue non enim.
24 |
Level 04 Heading
25 |
Sed scelerisque sagittis lorem. Phasellus sodales. Nulla urna justo, vehicula in, suscipit nec, molestie sed, tellus. Quisque justo. Nam libero leo, elementum in, dapibus a, suscipit vitae, purus. Duis arcu. Integer dignissim fermentum enim. Morbi convallis felis vel nibh. Etiam viverra augue non enim.
26 |
Level 05 Heading
27 |
28 |
Sed scelerisque sagittis lorem. Phasellus sodales. Nulla urna justo, vehicula in, suscipit nec, molestie sed, tellus. Quisque justo. Nam libero leo, elementum in, dapibus a, suscipit vitae, purus. Duis arcu. Integer dignissim fermentum enim. Morbi convallis felis vel nibh. Etiam viverra augue non enim.
29 |
Level 06 Heading
30 |
31 |
Sed scelerisque sagittis lorem. Phasellus sodales. Nulla urna justo, vehicula in, suscipit nec, molestie sed, tellus. Quisque justo. Nam libero leo, elementum in, dapibus a, suscipit vitae, purus. Duis arcu. Integer dignissim fermentum enim. Morbi convallis felis vel nibh. Etiam viverra augue non enim.
32 |
33 |
Paragraph inside Blockquote: Nam libero leo, elementum in, dapibus a, suscipit vitae, purus. Duis arcu. Integer dignissim fermentum enim. Morbi convallis felis vel nibh. Sed scelerisque sagittis lorem.
34 |
Paragraph inside Blockquote: Nam libero leo, elementum in, dapibus a, suscipit vitae, purus. Duis arcu. Integer dignissim fermentum enim. Morbi convallis felis vel nibh. Sed scelerisque sagittis lorem.
35 |
36 |
37 | Address: Example address 224, Sweden
38 |
Preformated:Testing one row
39 | and another
40 |
41 |
42 | I am the a tag example
43 |
44 | I am the abbr tag example
45 |
46 | I am the acronym tag example
47 |
48 | I am the b tag example
49 | I am the big tag example
50 |
51 | I am the cite tag example
52 |
53 | I am the code tag example
54 | I am the del tag example
55 | I am the dfn tag example
56 |
57 | I am the em tag example
58 |
59 | I am the i tag example
60 | I am the ins tag example
61 |
62 | I am the kbd tag example
63 |
64 | I am the q tag inside a q tag example
65 |
66 | I am the samp tag example
67 |
68 | I am the small tag example
69 | I am the span tag example
70 |
71 | I am the strong tag example
72 |
73 | I am the sub tag example
74 | I am the sup tag example
75 | I am the tt tag example
76 |
77 | I am the var tag example
78 |
79 |
80 |
81 |
Unordered list 01
82 |
Unordered list 02
83 |
84 |
Unordered list 03
85 |
86 |
87 |
Unordered list inside list level 2
88 |
89 |
Unordered list inside list level 2
90 |
91 |
Unordered list inside list level 3
92 |
Unordered list inside list level 3
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
Ordered list 01
103 |
Ordered list 02
104 |
105 |
Ordered list 03
106 |
107 |
Ordered list inside list level 2
108 |
109 |
Ordered list inside list level 2
110 |
111 |
112 |
'),x=b(''),g=b(''));if(!b.support.opacity){g.addClass("fancybox-ie");u.addClass("fancybox-ie")}D=b('').append('').appendTo(g);
36 | D.append(i=b(''),z=b(''),A=b(''),B=b(''));z.click(b.fancybox.close);u.click(b.fancybox.cancel);A.click(function(a){a.preventDefault();b.fancybox.prev()});B.click(function(a){a.preventDefault();b.fancybox.next()});if(O){x.get(0).style.setExpression("height",
37 | "document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'");u.get(0).style.setExpression("top","(-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px'");D.prepend('')}}};
38 | b.fn.fancybox=function(a){b(this).data("fancybox",b.extend({},a,b.metadata?b(this).metadata():{})).unbind("click.fb").bind("click.fb",function(d){d.preventDefault();if(!h){h=true;b(this).blur();q=[];p=0;d=b(this).attr("rel")||"";if(!d||d==""||d==="nofollow")q.push(this);else{q=b("a[rel="+d+"], area[rel="+d+"]");p=q.index(this)}C();return false}});return this};b.fancybox=function(a,d){if(!h){h=true;d=typeof d!=="undefined"?d:{};q=[];p=d.index||0;if(b.isArray(a)){for(var f=0,o=a.length;fq.length||p<0)p=0;C()}};b.fancybox.showActivity=function(){clearInterval(H);u.show();H=setInterval($,66)};b.fancybox.hideActivity=function(){u.hide()};b.fancybox.next=function(){return b.fancybox.pos(n+1)};b.fancybox.prev=function(){return b.fancybox.pos(n-
40 | 1)};b.fancybox.pos=function(a){if(!h){a=parseInt(a,10);if(a>-1&&j.length>a){p=a;C()}if(c.cyclic&&j.length>1&&a<0){p=j.length-1;C()}if(c.cyclic&&j.length>1&&a>=j.length){p=0;C()}}};b.fancybox.cancel=function(){if(!h){h=true;b.event.trigger("fancybox-cancel");J();e&&b.isFunction(e.onCancel)&&e.onCancel(q,p,e);h=false}};b.fancybox.close=function(){function a(){x.fadeOut("fast");g.hide();b.event.trigger("fancybox-cleanup");i.empty();b.isFunction(c.onClosed)&&c.onClosed(j,n,c);j=e=[];n=p=0;c=e={};h=false}
41 | if(!(h||g.is(":hidden"))){h=true;if(c&&b.isFunction(c.onCleanup))if(c.onCleanup(j,n,c)===false){h=false;return}J();b(z.add(A).add(B)).hide();b("#fancybox-title").remove();g.add(i).add(x).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");i.css("overflow","hidden");if(c.transitionOut=="elastic"){k=Q();var d=g.position();l={top:d.top,left:d.left,width:g.width(),height:g.height()};if(c.opacity)l.opacity=1;y.prop=1;b(y).animate({prop:0},{duration:c.speedOut,easing:c.easingOut,
42 | step:M,complete:a})}else g.fadeOut(c.transitionOut=="none"?0:c.speedOut,a)}};b.fancybox.resize=function(){var a,d;if(!(h||g.is(":hidden"))){h=true;a=i.wrapInner("").children();d=a.height();g.css({height:d+c.padding*2+v});i.css({height:d});a.replaceWith(a.children());b.fancybox.center()}};b.fancybox.center=function(){h=true;var a=K(),d=c.margin,f={};f.top=a[3]+(a[1]-(g.height()-v+40))*0.5;f.left=a[2]+(a[0]-(g.width()+40))*0.5;f.top=Math.max(a[3]+d,f.top);f.left=Math.max(a[2]+
43 | d,f.left);g.css(f);h=false};b.fn.fancybox.defaults={padding:10,margin:20,opacity:false,modal:false,cyclic:false,scrolling:"auto",width:560,height:340,autoScale:true,autoDimensions:true,centerOnScroll:false,ajax:{},swf:{wmode:"transparent"},hideOnOverlayClick:true,hideOnContentClick:false,overlayShow:true,overlayOpacity:0.3,overlayColor:"#666",titleShow:true,titlePosition:"outside",titleFormat:null,transitionIn:"fade",transitionOut:"fade",speedIn:300,speedOut:300,changeSpeed:300,changeFade:"fast",
44 | easingIn:"swing",easingOut:"swing",showCloseButton:true,showNavArrows:true,enableEscapeButton:true,onStart:null,onCancel:null,onComplete:null,onCleanup:null,onClosed:null};b(document).ready(function(){aa()})})(jQuery);
--------------------------------------------------------------------------------
/mineral/static/mineral/js/plugins/jquery.jcarousellite-1.0.1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * jCarouselLite - jQuery plugin to navigate images/any content in a carousel style widget.
3 | * @requires jQuery v1.2 or above
4 | *
5 | * http://gmarwaha.com/jquery/jcarousellite/
6 | *
7 | * Copyright (c) 2007 Ganeshji Marwaha (gmarwaha.com)
8 | * Dual licensed under the MIT and GPL licenses:
9 | * http://www.opensource.org/licenses/mit-license.php
10 | * http://www.gnu.org/licenses/gpl.html
11 | *
12 | * Version: 1.0.1
13 | * Note: Requires jquery 1.2 or above from version 1.0.1
14 | */
15 |
16 | /**
17 | * Creates a carousel-style navigation widget for images/any-content from a simple HTML markup.
18 | *
19 | * The HTML markup that is used to build the carousel can be as simple as...
20 | *
21 | *
22 | *
23 | *
24 | *
25 | *
26 | *
27 | *
28 | *
29 | * As you can see, this snippet is nothing but a simple div containing an unordered list of images.
30 | * You don't need any special "class" attribute, or a special "css" file for this plugin.
31 | * I am using a class attribute just for the sake of explanation here.
32 | *
33 | * To navigate the elements of the carousel, you need some kind of navigation buttons.
34 | * For example, you will need a "previous" button to go backward, and a "next" button to go forward.
35 | * This need not be part of the carousel "div" itself. It can be any element in your page.
36 | * Lets assume that the following elements in your document can be used as next, and prev buttons...
37 | *
38 | *
39 | *
40 | *
41 | * Now, all you need to do is call the carousel component on the div element that represents it, and pass in the
42 | * navigation buttons as options.
43 | *
44 | * $(".carousel").jCarouselLite({
45 | * btnNext: ".next",
46 | * btnPrev: ".prev"
47 | * });
48 | *
49 | * That's it, you would have now converted your raw div, into a magnificient carousel.
50 | *
51 | * There are quite a few other options that you can use to customize it though.
52 | * Each will be explained with an example below.
53 | *
54 | * @param an options object - You can specify all the options shown below as an options object param.
55 | *
56 | * @option btnPrev, btnNext : string - no defaults
57 | * @example
58 | * $(".carousel").jCarouselLite({
59 | * btnNext: ".next",
60 | * btnPrev: ".prev"
61 | * });
62 | * @desc Creates a basic carousel. Clicking "btnPrev" navigates backwards and "btnNext" navigates forward.
63 | *
64 | * @option btnGo - array - no defaults
65 | * @example
66 | * $(".carousel").jCarouselLite({
67 | * btnNext: ".next",
68 | * btnPrev: ".prev",
69 | * btnGo: [".0", ".1", ".2"]
70 | * });
71 | * @desc If you don't want next and previous buttons for navigation, instead you prefer custom navigation based on
72 | * the item number within the carousel, you can use this option. Just supply an array of selectors for each element
73 | * in the carousel. The index of the array represents the index of the element. What i mean is, if the
74 | * first element in the array is ".0", it means that when the element represented by ".0" is clicked, the carousel
75 | * will slide to the first element and so on and so forth. This feature is very powerful. For example, i made a tabbed
76 | * interface out of it by making my navigation elements styled like tabs in css. As the carousel is capable of holding
77 | * any content, not just images, you can have a very simple tabbed navigation in minutes without using any other plugin.
78 | * The best part is that, the tab will "slide" based on the provided effect. :-)
79 | *
80 | * @option mouseWheel : boolean - default is false
81 | * @example
82 | * $(".carousel").jCarouselLite({
83 | * mouseWheel: true
84 | * });
85 | * @desc The carousel can also be navigated using the mouse wheel interface of a scroll mouse instead of using buttons.
86 | * To get this feature working, you have to do 2 things. First, you have to include the mouse-wheel plugin from brandon.
87 | * Second, you will have to set the option "mouseWheel" to true. That's it, now you will be able to navigate your carousel
88 | * using the mouse wheel. Using buttons and mouseWheel or not mutually exclusive. You can still have buttons for navigation
89 | * as well. They complement each other. To use both together, just supply the options required for both as shown below.
90 | * @example
91 | * $(".carousel").jCarouselLite({
92 | * btnNext: ".next",
93 | * btnPrev: ".prev",
94 | * mouseWheel: true
95 | * });
96 | *
97 | * @option auto : number - default is null, meaning autoscroll is disabled by default
98 | * @example
99 | * $(".carousel").jCarouselLite({
100 | * auto: 800,
101 | * speed: 500
102 | * });
103 | * @desc You can make your carousel auto-navigate itself by specfying a millisecond value in this option.
104 | * The value you specify is the amount of time between 2 slides. The default is null, and that disables auto scrolling.
105 | * Specify this value and magically your carousel will start auto scrolling.
106 | *
107 | * @option speed : number - 200 is default
108 | * @example
109 | * $(".carousel").jCarouselLite({
110 | * btnNext: ".next",
111 | * btnPrev: ".prev",
112 | * speed: 800
113 | * });
114 | * @desc Specifying a speed will slow-down or speed-up the sliding speed of your carousel. Try it out with
115 | * different speeds like 800, 600, 1500 etc. Providing 0, will remove the slide effect.
116 | *
117 | * @option easing : string - no easing effects by default.
118 | * @example
119 | * $(".carousel").jCarouselLite({
120 | * btnNext: ".next",
121 | * btnPrev: ".prev",
122 | * easing: "bounceout"
123 | * });
124 | * @desc You can specify any easing effect. Note: You need easing plugin for that. Once specified,
125 | * the carousel will slide based on the provided easing effect.
126 | *
127 | * @option vertical : boolean - default is false
128 | * @example
129 | * $(".carousel").jCarouselLite({
130 | * btnNext: ".next",
131 | * btnPrev: ".prev",
132 | * vertical: true
133 | * });
134 | * @desc Determines the direction of the carousel. true, means the carousel will display vertically. The next and
135 | * prev buttons will slide the items vertically as well. The default is false, which means that the carousel will
136 | * display horizontally. The next and prev items will slide the items from left-right in this case.
137 | *
138 | * @option circular : boolean - default is true
139 | * @example
140 | * $(".carousel").jCarouselLite({
141 | * btnNext: ".next",
142 | * btnPrev: ".prev",
143 | * circular: false
144 | * });
145 | * @desc Setting it to true enables circular navigation. This means, if you click "next" after you reach the last
146 | * element, you will automatically slide to the first element and vice versa. If you set circular to false, then
147 | * if you click on the "next" button after you reach the last element, you will stay in the last element itself
148 | * and similarly for "previous" button and first element.
149 | *
150 | * @option visible : number - default is 3
151 | * @example
152 | * $(".carousel").jCarouselLite({
153 | * btnNext: ".next",
154 | * btnPrev: ".prev",
155 | * visible: 4
156 | * });
157 | * @desc This specifies the number of items visible at all times within the carousel. The default is 3.
158 | * You are even free to experiment with real numbers. Eg: "3.5" will have 3 items fully visible and the
159 | * last item half visible. This gives you the effect of showing the user that there are more images to the right.
160 | *
161 | * @option start : number - default is 0
162 | * @example
163 | * $(".carousel").jCarouselLite({
164 | * btnNext: ".next",
165 | * btnPrev: ".prev",
166 | * start: 2
167 | * });
168 | * @desc You can specify from which item the carousel should start. Remember, the first item in the carousel
169 | * has a start of 0, and so on.
170 | *
171 | * @option scrool : number - default is 1
172 | * @example
173 | * $(".carousel").jCarouselLite({
174 | * btnNext: ".next",
175 | * btnPrev: ".prev",
176 | * scroll: 2
177 | * });
178 | * @desc The number of items that should scroll/slide when you click the next/prev navigation buttons. By
179 | * default, only one item is scrolled, but you may set it to any number. Eg: setting it to "2" will scroll
180 | * 2 items when you click the next or previous buttons.
181 | *
182 | * @option beforeStart, afterEnd : function - callbacks
183 | * @example
184 | * $(".carousel").jCarouselLite({
185 | * btnNext: ".next",
186 | * btnPrev: ".prev",
187 | * beforeStart: function(a) {
188 | * alert("Before animation starts:" + a);
189 | * },
190 | * afterEnd: function(a) {
191 | * alert("After animation ends:" + a);
192 | * }
193 | * });
194 | * @desc If you wanted to do some logic in your page before the slide starts and after the slide ends, you can
195 | * register these 2 callbacks. The functions will be passed an argument that represents an array of elements that
196 | * are visible at the time of callback.
197 | *
198 | *
199 | * @cat Plugins/Image Gallery
200 | * @author Ganeshji Marwaha/ganeshread@gmail.com
201 | */
202 |
203 | (function($) { // Compliant with jquery.noConflict()
204 | $.fn.jCarouselLite = function(o) {
205 | o = $.extend({
206 | btnPrev: null,
207 | btnNext: null,
208 | btnGo: null,
209 | mouseWheel: false,
210 | auto: null,
211 |
212 | speed: 200,
213 | easing: null,
214 |
215 | vertical: false,
216 | circular: true,
217 | visible: 3,
218 | start: 0,
219 | scroll: 1,
220 |
221 | beforeStart: null,
222 | afterEnd: null
223 | }, o || {});
224 |
225 | return this.each(function() { // Returns the element collection. Chainable.
226 |
227 | var running = false, animCss=o.vertical?"top":"left", sizeCss=o.vertical?"height":"width";
228 | var div = $(this), ul = $("ul", div), tLi = $("li", ul), tl = tLi.size(), v = o.visible;
229 |
230 | if(o.circular) {
231 | ul.prepend(tLi.slice(tl-v-1+1).clone())
232 | .append(tLi.slice(0,v).clone());
233 | o.start += v;
234 | }
235 |
236 | var li = $("li", ul), itemLength = li.size(), curr = o.start;
237 | div.css("visibility", "visible");
238 |
239 | li.css({overflow: "hidden", float: o.vertical ? "none" : "left"});
240 | ul.css({margin: "0", padding: "0", position: "relative", "list-style-type": "none", "z-index": "1"});
241 | div.css({overflow: "hidden", position: "relative", "z-index": "2", left: "0px"});
242 |
243 | var liSize = o.vertical ? height(li) : width(li); // Full li size(incl margin)-Used for animation
244 | var ulSize = liSize * itemLength; // size of full ul(total length, not just for the visible items)
245 | var divSize = liSize * v; // size of entire div(total length for just the visible items)
246 |
247 | li.css({width: li.width(), height: li.height()});
248 | ul.css(sizeCss, ulSize+"px").css(animCss, -(curr*liSize));
249 |
250 | div.css(sizeCss, divSize+"px"); // Width of the DIV. length of visible images
251 |
252 | if(o.btnPrev)
253 | $(o.btnPrev).click(function() {
254 | return go(curr-o.scroll);
255 | });
256 |
257 | if(o.btnNext)
258 | $(o.btnNext).click(function() {
259 | return go(curr+o.scroll);
260 | });
261 |
262 | if(o.btnGo)
263 | $.each(o.btnGo, function(i, val) {
264 | $(val).click(function() {
265 | return go(o.circular ? o.visible+i : i);
266 | });
267 | });
268 |
269 | if(o.mouseWheel && div.mousewheel)
270 | div.mousewheel(function(e, d) {
271 | return d>0 ? go(curr-o.scroll) : go(curr+o.scroll);
272 | });
273 |
274 | if(o.auto)
275 | setInterval(function() {
276 | go(curr+o.scroll);
277 | }, o.auto+o.speed);
278 |
279 | function vis() {
280 | return li.slice(curr).slice(0,v);
281 | };
282 |
283 | function go(to) {
284 | if(!running) {
285 |
286 | if(o.beforeStart)
287 | o.beforeStart.call(this, vis());
288 |
289 | if(o.circular) { // If circular we are in first or last, then goto the other end
290 | if(to<=o.start-v-1) { // If first, then goto last
291 | ul.css(animCss, -((itemLength-(v*2))*liSize)+"px");
292 | // If "scroll" > 1, then the "to" might not be equal to the condition; it can be lesser depending on the number of elements.
293 | curr = to==o.start-v-1 ? itemLength-(v*2)-1 : itemLength-(v*2)-o.scroll;
294 | } else if(to>=itemLength-v+1) { // If last, then goto first
295 | ul.css(animCss, -( (v) * liSize ) + "px" );
296 | // If "scroll" > 1, then the "to" might not be equal to the condition; it can be greater depending on the number of elements.
297 | curr = to==itemLength-v+1 ? v+1 : v+o.scroll;
298 | } else curr = to;
299 | } else { // If non-circular and to points to first or last, we just return.
300 | if(to<0 || to>itemLength-v) return;
301 | else curr = to;
302 | } // If neither overrides it, the curr will still be "to" and we can proceed.
303 |
304 | running = true;
305 |
306 | ul.animate(
307 | animCss == "left" ? { left: -(curr*liSize) } : { top: -(curr*liSize) } , o.speed, o.easing,
308 | function() {
309 | if(o.afterEnd)
310 | o.afterEnd.call(this, vis());
311 | running = false;
312 | }
313 | );
314 | // Disable buttons when the carousel reaches the last/first, and enable when not
315 | if(!o.circular) {
316 | $(o.btnPrev + "," + o.btnNext).removeClass("disabled");
317 | $( (curr-o.scroll<0 && o.btnPrev)
318 | ||
319 | (curr+o.scroll > itemLength-v && o.btnNext)
320 | ||
321 | []
322 | ).addClass("disabled");
323 | }
324 |
325 | }
326 | return false;
327 | };
328 | });
329 | };
330 |
331 | function css(el, prop) {
332 | return parseInt($.css(el[0], prop)) || 0;
333 | };
334 | function width(el) {
335 | return el[0].offsetWidth + css(el, 'marginLeft') + css(el, 'marginRight');
336 | };
337 | function height(el) {
338 | return el[0].offsetHeight + css(el, 'marginTop') + css(el, 'marginBottom');
339 | };
340 |
341 | })(jQuery);
--------------------------------------------------------------------------------
/mineral/static/mineral/js/libs/json2.js:
--------------------------------------------------------------------------------
1 | /*
2 | http://www.JSON.org/json2.js
3 | 2008-07-15
4 |
5 | Public Domain.
6 |
7 | NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
8 |
9 | See http://www.JSON.org/js.html
10 |
11 | This file creates a global JSON object containing two methods: stringify
12 | and parse.
13 |
14 | JSON.stringify(value, replacer, space)
15 | value any JavaScript value, usually an object or array.
16 |
17 | replacer an optional parameter that determines how object
18 | values are stringified for objects. It can be a
19 | function or an array.
20 |
21 | space an optional parameter that specifies the indentation
22 | of nested structures. If it is omitted, the text will
23 | be packed without extra whitespace. If it is a number,
24 | it will specify the number of spaces to indent at each
25 | level. If it is a string (such as '\t' or ' '),
26 | it contains the characters used to indent at each level.
27 |
28 | This method produces a JSON text from a JavaScript value.
29 |
30 | When an object value is found, if the object contains a toJSON
31 | method, its toJSON method will be called and the result will be
32 | stringified. A toJSON method does not serialize: it returns the
33 | value represented by the name/value pair that should be serialized,
34 | or undefined if nothing should be serialized. The toJSON method
35 | will be passed the key associated with the value, and this will be
36 | bound to the object holding the key.
37 |
38 | For example, this would serialize Dates as ISO strings.
39 |
40 | Date.prototype.toJSON = function (key) {
41 | function f(n) {
42 | // Format integers to have at least two digits.
43 | return n < 10 ? '0' + n : n;
44 | }
45 |
46 | return this.getUTCFullYear() + '-' +
47 | f(this.getUTCMonth() + 1) + '-' +
48 | f(this.getUTCDate()) + 'T' +
49 | f(this.getUTCHours()) + ':' +
50 | f(this.getUTCMinutes()) + ':' +
51 | f(this.getUTCSeconds()) + 'Z';
52 | };
53 |
54 | You can provide an optional replacer method. It will be passed the
55 | key and value of each member, with this bound to the containing
56 | object. The value that is returned from your method will be
57 | serialized. If your method returns undefined, then the member will
58 | be excluded from the serialization.
59 |
60 | If the replacer parameter is an array, then it will be used to
61 | select the members to be serialized. It filters the results such
62 | that only members with keys listed in the replacer array are
63 | stringified.
64 |
65 | Values that do not have JSON representations, such as undefined or
66 | functions, will not be serialized. Such values in objects will be
67 | dropped; in arrays they will be replaced with null. You can use
68 | a replacer function to replace those with JSON values.
69 | JSON.stringify(undefined) returns undefined.
70 |
71 | The optional space parameter produces a stringification of the
72 | value that is filled with line breaks and indentation to make it
73 | easier to read.
74 |
75 | If the space parameter is a non-empty string, then that string will
76 | be used for indentation. If the space parameter is a number, then
77 | the indentation will be that many spaces.
78 |
79 | Example:
80 |
81 | text = JSON.stringify(['e', {pluribus: 'unum'}]);
82 | // text is '["e",{"pluribus":"unum"}]'
83 |
84 |
85 | text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
86 | // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
87 |
88 | text = JSON.stringify([new Date()], function (key, value) {
89 | return this[key] instanceof Date ?
90 | 'Date(' + this[key] + ')' : value;
91 | });
92 | // text is '["Date(---current time---)"]'
93 |
94 |
95 | JSON.parse(text, reviver)
96 | This method parses a JSON text to produce an object or array.
97 | It can throw a SyntaxError exception.
98 |
99 | The optional reviver parameter is a function that can filter and
100 | transform the results. It receives each of the keys and values,
101 | and its return value is used instead of the original value.
102 | If it returns what it received, then the structure is not modified.
103 | If it returns undefined then the member is deleted.
104 |
105 | Example:
106 |
107 | // Parse the text. Values that look like ISO date strings will
108 | // be converted to Date objects.
109 |
110 | myData = JSON.parse(text, function (key, value) {
111 | var a;
112 | if (typeof value === 'string') {
113 | a =
114 | /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
115 | if (a) {
116 | return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
117 | +a[5], +a[6]));
118 | }
119 | }
120 | return value;
121 | });
122 |
123 | myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
124 | var d;
125 | if (typeof value === 'string' &&
126 | value.slice(0, 5) === 'Date(' &&
127 | value.slice(-1) === ')') {
128 | d = new Date(value.slice(5, -1));
129 | if (d) {
130 | return d;
131 | }
132 | }
133 | return value;
134 | });
135 |
136 |
137 | This is a reference implementation. You are free to copy, modify, or
138 | redistribute.
139 |
140 | This code should be minified before deployment.
141 | See http://javascript.crockford.com/jsmin.html
142 |
143 | USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
144 | NOT CONTROL.
145 | */
146 |
147 | /*jslint evil: true */
148 |
149 | /*global JSON */
150 |
151 | /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", call,
152 | charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, getUTCMinutes,
153 | getUTCMonth, getUTCSeconds, hasOwnProperty, join, lastIndex, length,
154 | parse, propertyIsEnumerable, prototype, push, replace, slice, stringify,
155 | test, toJSON, toString
156 | */
157 |
158 | if (!this.JSON) {
159 |
160 | // Create a JSON object only if one does not already exist. We create the
161 | // object in a closure to avoid creating global variables.
162 |
163 | JSON = function () {
164 |
165 | function f(n) {
166 | // Format integers to have at least two digits.
167 | return n < 10 ? '0' + n : n;
168 | }
169 |
170 | Date.prototype.toJSON = function (key) {
171 |
172 | return this.getUTCFullYear() + '-' +
173 | f(this.getUTCMonth() + 1) + '-' +
174 | f(this.getUTCDate()) + 'T' +
175 | f(this.getUTCHours()) + ':' +
176 | f(this.getUTCMinutes()) + ':' +
177 | f(this.getUTCSeconds()) + 'Z';
178 | };
179 |
180 | String.prototype.toJSON =
181 | Number.prototype.toJSON =
182 | Boolean.prototype.toJSON = function (key) {
183 | return this.valueOf();
184 | };
185 |
186 | var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
187 | escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
188 | gap,
189 | indent,
190 | meta = { // table of character substitutions
191 | '\b': '\\b',
192 | '\t': '\\t',
193 | '\n': '\\n',
194 | '\f': '\\f',
195 | '\r': '\\r',
196 | '"' : '\\"',
197 | '\\': '\\\\'
198 | },
199 | rep;
200 |
201 |
202 | function quote(string) {
203 |
204 | // If the string contains no control characters, no quote characters, and no
205 | // backslash characters, then we can safely slap some quotes around it.
206 | // Otherwise we must also replace the offending characters with safe escape
207 | // sequences.
208 |
209 | escapeable.lastIndex = 0;
210 | return escapeable.test(string) ?
211 | '"' + string.replace(escapeable, function (a) {
212 | var c = meta[a];
213 | if (typeof c === 'string') {
214 | return c;
215 | }
216 | return '\\u' + ('0000' +
217 | (+(a.charCodeAt(0))).toString(16)).slice(-4);
218 | }) + '"' :
219 | '"' + string + '"';
220 | }
221 |
222 |
223 | function str(key, holder) {
224 |
225 | // Produce a string from holder[key].
226 |
227 | var i, // The loop counter.
228 | k, // The member key.
229 | v, // The member value.
230 | length,
231 | mind = gap,
232 | partial,
233 | value = holder[key];
234 |
235 | // If the value has a toJSON method, call it to obtain a replacement value.
236 |
237 | if (value && typeof value === 'object' &&
238 | typeof value.toJSON === 'function') {
239 | value = value.toJSON(key);
240 | }
241 |
242 | // If we were called with a replacer function, then call the replacer to
243 | // obtain a replacement value.
244 |
245 | if (typeof rep === 'function') {
246 | value = rep.call(holder, key, value);
247 | }
248 |
249 | // What happens next depends on the value's type.
250 |
251 | switch (typeof value) {
252 | case 'string':
253 | return quote(value);
254 |
255 | case 'number':
256 |
257 | // JSON numbers must be finite. Encode non-finite numbers as null.
258 |
259 | return isFinite(value) ? String(value) : 'null';
260 |
261 | case 'boolean':
262 | case 'null':
263 |
264 | // If the value is a boolean or null, convert it to a string. Note:
265 | // typeof null does not produce 'null'. The case is included here in
266 | // the remote chance that this gets fixed someday.
267 |
268 | return String(value);
269 |
270 | // If the type is 'object', we might be dealing with an object or an array or
271 | // null.
272 |
273 | case 'object':
274 |
275 | // Due to a specification blunder in ECMAScript, typeof null is 'object',
276 | // so watch out for that case.
277 |
278 | if (!value) {
279 | return 'null';
280 | }
281 |
282 | // Make an array to hold the partial results of stringifying this object value.
283 |
284 | gap += indent;
285 | partial = [];
286 |
287 | // If the object has a dontEnum length property, we'll treat it as an array.
288 |
289 | if (typeof value.length === 'number' &&
290 | !(value.propertyIsEnumerable('length'))) {
291 |
292 | // The object is an array. Stringify every element. Use null as a placeholder
293 | // for non-JSON values.
294 |
295 | length = value.length;
296 | for (i = 0; i < length; i += 1) {
297 | partial[i] = str(i, value) || 'null';
298 | }
299 |
300 | // Join all of the elements together, separated with commas, and wrap them in
301 | // brackets.
302 |
303 | v = partial.length === 0 ? '[]' :
304 | gap ? '[\n' + gap +
305 | partial.join(',\n' + gap) + '\n' +
306 | mind + ']' :
307 | '[' + partial.join(',') + ']';
308 | gap = mind;
309 | return v;
310 | }
311 |
312 | // If the replacer is an array, use it to select the members to be stringified.
313 |
314 | if (rep && typeof rep === 'object') {
315 | length = rep.length;
316 | for (i = 0; i < length; i += 1) {
317 | k = rep[i];
318 | if (typeof k === 'string') {
319 | v = str(k, value);
320 | if (v) {
321 | partial.push(quote(k) + (gap ? ': ' : ':') + v);
322 | }
323 | }
324 | }
325 | } else {
326 |
327 | // Otherwise, iterate through all of the keys in the object.
328 |
329 | for (k in value) {
330 | if (Object.hasOwnProperty.call(value, k)) {
331 | v = str(k, value);
332 | if (v) {
333 | partial.push(quote(k) + (gap ? ': ' : ':') + v);
334 | }
335 | }
336 | }
337 | }
338 |
339 | // Join all of the member texts together, separated with commas,
340 | // and wrap them in braces.
341 |
342 | v = partial.length === 0 ? '{}' :
343 | gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
344 | mind + '}' : '{' + partial.join(',') + '}';
345 | gap = mind;
346 | return v;
347 | }
348 | }
349 |
350 | // Return the JSON object containing the stringify and parse methods.
351 |
352 | return {
353 | stringify: function (value, replacer, space) {
354 |
355 | // The stringify method takes a value and an optional replacer, and an optional
356 | // space parameter, and returns a JSON text. The replacer can be a function
357 | // that can replace values, or an array of strings that will select the keys.
358 | // A default replacer method can be provided. Use of the space parameter can
359 | // produce text that is more easily readable.
360 |
361 | var i;
362 | gap = '';
363 | indent = '';
364 |
365 | // If the space parameter is a number, make an indent string containing that
366 | // many spaces.
367 |
368 | if (typeof space === 'number') {
369 | for (i = 0; i < space; i += 1) {
370 | indent += ' ';
371 | }
372 |
373 | // If the space parameter is a string, it will be used as the indent string.
374 |
375 | } else if (typeof space === 'string') {
376 | indent = space;
377 | }
378 |
379 | // If there is a replacer, it must be a function or an array.
380 | // Otherwise, throw an error.
381 |
382 | rep = replacer;
383 | if (replacer && typeof replacer !== 'function' &&
384 | (typeof replacer !== 'object' ||
385 | typeof replacer.length !== 'number')) {
386 | throw new Error('JSON.stringify');
387 | }
388 |
389 | // Make a fake root object containing our value under the key of ''.
390 | // Return the result of stringifying the value.
391 |
392 | return str('', {'': value});
393 | },
394 |
395 |
396 | parse: function (text, reviver) {
397 |
398 | // The parse method takes a text and an optional reviver function, and returns
399 | // a JavaScript value if the text is a valid JSON text.
400 |
401 | var j;
402 |
403 | function walk(holder, key) {
404 |
405 | // The walk method is used to recursively walk the resulting structure so
406 | // that modifications can be made.
407 |
408 | var k, v, value = holder[key];
409 | if (value && typeof value === 'object') {
410 | for (k in value) {
411 | if (Object.hasOwnProperty.call(value, k)) {
412 | v = walk(value, k);
413 | if (v !== undefined) {
414 | value[k] = v;
415 | } else {
416 | delete value[k];
417 | }
418 | }
419 | }
420 | }
421 | return reviver.call(holder, key, value);
422 | }
423 |
424 |
425 | // Parsing happens in four stages. In the first stage, we replace certain
426 | // Unicode characters with escape sequences. JavaScript handles many characters
427 | // incorrectly, either silently deleting them, or treating them as line endings.
428 |
429 | cx.lastIndex = 0;
430 | if (cx.test(text)) {
431 | text = text.replace(cx, function (a) {
432 | return '\\u' + ('0000' +
433 | (+(a.charCodeAt(0))).toString(16)).slice(-4);
434 | });
435 | }
436 |
437 | // In the second stage, we run the text against regular expressions that look
438 | // for non-JSON patterns. We are especially concerned with '()' and 'new'
439 | // because they can cause invocation, and '=' because it can cause mutation.
440 | // But just to be safe, we want to reject all unexpected forms.
441 |
442 | // We split the second stage into 4 regexp operations in order to work around
443 | // crippling inefficiencies in IE's and Safari's regexp engines. First we
444 | // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
445 | // replace all simple value tokens with ']' characters. Third, we delete all
446 | // open brackets that follow a colon or comma or that begin the text. Finally,
447 | // we look to see that the remaining characters are only whitespace or ']' or
448 | // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
449 |
450 | if (/^[\],:{}\s]*$/.
451 | test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
452 | replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
453 | replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
454 |
455 | // In the third stage we use the eval function to compile the text into a
456 | // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
457 | // in JavaScript: it can begin a block or an object literal. We wrap the text
458 | // in parens to eliminate the ambiguity.
459 |
460 | j = eval('(' + text + ')');
461 |
462 | // In the optional fourth stage, we recursively walk the new structure, passing
463 | // each name/value pair to a reviver function for possible transformation.
464 |
465 | return typeof reviver === 'function' ?
466 | walk({'': j}, '') : j;
467 | }
468 |
469 | // If the text is not JSON parseable, then a SyntaxError is thrown.
470 |
471 | throw new SyntaxError('JSON.parse');
472 | }
473 | };
474 | }();
475 | }
476 |
--------------------------------------------------------------------------------
/mineral/static/mineral/js/plugins/jquery.multifile.js:
--------------------------------------------------------------------------------
1 | /*
2 | ### jQuery Multiple File Upload Plugin v1.47 - 2010-03-26 ###
3 | * Home: http://www.fyneworks.com/jquery/multiple-file-upload/
4 | * Code: http://code.google.com/p/jquery-multifile-plugin/
5 | *
6 | * Dual licensed under the MIT and GPL licenses:
7 | * http://www.opensource.org/licenses/mit-license.php
8 | * http://www.gnu.org/licenses/gpl.html
9 | ###
10 | */
11 |
12 | /*# AVOID COLLISIONS #*/
13 | ;if(window.jQuery) (function($){
14 | /*# AVOID COLLISIONS #*/
15 |
16 | // plugin initialization
17 | $.fn.MultiFile = function(options){
18 | if(this.length==0) return this; // quick fail
19 |
20 | // Handle API methods
21 | if(typeof arguments[0]=='string'){
22 | // Perform API methods on individual elements
23 | if(this.length>1){
24 | var args = arguments;
25 | return this.each(function(){
26 | $.fn.MultiFile.apply($(this), args);
27 | });
28 | };
29 | // Invoke API method handler
30 | $.fn.MultiFile[arguments[0]].apply(this, $.makeArray(arguments).slice(1) || []);
31 | // Quick exit...
32 | return this;
33 | };
34 |
35 | // Initialize options for this call
36 | var options = $.extend(
37 | {}/* new object */,
38 | $.fn.MultiFile.options/* default options */,
39 | options || {} /* just-in-time options */
40 | );
41 |
42 | // Empty Element Fix!!!
43 | // this code will automatically intercept native form submissions
44 | // and disable empty file elements
45 | $('form')
46 | .not('MultiFile-intercepted')
47 | .addClass('MultiFile-intercepted')
48 | .submit($.fn.MultiFile.disableEmpty);
49 |
50 | //### http://plugins.jquery.com/node/1363
51 | // utility method to integrate this plugin with others...
52 | if($.fn.MultiFile.options.autoIntercept){
53 | $.fn.MultiFile.intercept( $.fn.MultiFile.options.autoIntercept /* array of methods to intercept */ );
54 | $.fn.MultiFile.options.autoIntercept = null; /* only run this once */
55 | };
56 |
57 | // loop through each matched element
58 | this
59 | .not('.MultiFile-applied')
60 | .addClass('MultiFile-applied')
61 | .each(function(){
62 | //#####################################################################
63 | // MAIN PLUGIN FUNCTIONALITY - START
64 | //#####################################################################
65 |
66 | // BUG 1251 FIX: http://plugins.jquery.com/project/comments/add/1251
67 | // variable group_count would repeat itself on multiple calls to the plugin.
68 | // this would cause a conflict with multiple elements
69 | // changes scope of variable to global so id will be unique over n calls
70 | window.MultiFile = (window.MultiFile || 0) + 1;
71 | var group_count = window.MultiFile;
72 |
73 | // Copy parent attributes - Thanks to Jonas Wagner
74 | // we will use this one to create new input elements
75 | var MultiFile = {e:this, E:$(this), clone:$(this).clone()};
76 |
77 | //===
78 |
79 | //# USE CONFIGURATION
80 | if(typeof options=='number') options = {max:options};
81 | var o = $.extend({},
82 | $.fn.MultiFile.options,
83 | options || {},
84 | ($.metadata? MultiFile.E.metadata(): ($.meta?MultiFile.E.data():null)) || {}, /* metadata options */
85 | {} /* internals */
86 | );
87 | // limit number of files that can be selected?
88 | if(!(o.max>0) /*IsNull(MultiFile.max)*/){
89 | o.max = MultiFile.E.attr('maxlength');
90 | if(!(o.max>0) /*IsNull(MultiFile.max)*/){
91 | o.max = (String(MultiFile.e.className.match(/\b(max|limit)\-([0-9]+)\b/gi) || ['']).match(/[0-9]+/gi) || [''])[0];
92 | if(!(o.max>0)) o.max = -1;
93 | else o.max = String(o.max).match(/[0-9]+/gi)[0];
94 | }
95 | };
96 | o.max = new Number(o.max);
97 | // limit extensions?
98 | o.accept = o.accept || MultiFile.E.attr('accept') || '';
99 | if(!o.accept){
100 | o.accept = (MultiFile.e.className.match(/\b(accept\-[\w\|]+)\b/gi)) || '';
101 | o.accept = new String(o.accept).replace(/^(accept|ext)\-/i,'');
102 | };
103 |
104 | //===
105 |
106 | // APPLY CONFIGURATION
107 | $.extend(MultiFile, o || {});
108 | MultiFile.STRING = $.extend({},$.fn.MultiFile.options.STRING,MultiFile.STRING);
109 |
110 | //===
111 |
112 | //#########################################
113 | // PRIVATE PROPERTIES/METHODS
114 | $.extend(MultiFile, {
115 | n: 0, // How many elements are currently selected?
116 | slaves: [], files: [],
117 | instanceKey: MultiFile.e.id || 'MultiFile'+String(group_count), // Instance Key?
118 | generateID: function(z){ return MultiFile.instanceKey + (z>0 ?'_F'+String(z):''); },
119 | trigger: function(event, element){
120 | var handler = MultiFile[event], value = $(element).attr('value');
121 | if(handler){
122 | var returnValue = handler(element, value, MultiFile);
123 | if( returnValue!=null ) return returnValue;
124 | }
125 | return true;
126 | }
127 | });
128 |
129 | //===
130 |
131 | // Setup dynamic regular expression for extension validation
132 | // - thanks to John-Paul Bader: http://smyck.de/2006/08/11/javascript-dynamic-regular-expresions/
133 | if(String(MultiFile.accept).length>1){
134 | MultiFile.accept = MultiFile.accept.replace(/\W+/g,'|').replace(/^\W|\W$/g,'');
135 | MultiFile.rxAccept = new RegExp('\\.('+(MultiFile.accept?MultiFile.accept:'')+')$','gi');
136 | };
137 |
138 | //===
139 |
140 | // Create wrapper to hold our file list
141 | MultiFile.wrapID = MultiFile.instanceKey+'_wrap'; // Wrapper ID?
142 | MultiFile.E.wrap('');
143 | MultiFile.wrapper = $('#'+MultiFile.wrapID+'');
144 |
145 | //===
146 |
147 | // MultiFile MUST have a name - default: file1[], file2[], file3[]
148 | MultiFile.e.name = MultiFile.e.name || 'file'+ group_count +'[]';
149 |
150 | //===
151 |
152 | if(!MultiFile.list){
153 | // Create a wrapper for the list
154 | // * OPERA BUG: NO_MODIFICATION_ALLOWED_ERR ('list' is a read-only property)
155 | // this change allows us to keep the files in the order they were selected
156 | MultiFile.wrapper.append( '' );
157 | MultiFile.list = $('#'+MultiFile.wrapID+'_list');
158 | };
159 | MultiFile.list = $(MultiFile.list);
160 |
161 | //===
162 |
163 | // Bind a new element
164 | MultiFile.addSlave = function( slave, slave_count ){
165 | //if(window.console) console.log('MultiFile.addSlave',slave_count);
166 |
167 | // Keep track of how many elements have been displayed
168 | MultiFile.n++;
169 | // Add reference to master element
170 | slave.MultiFile = MultiFile;
171 |
172 | // BUG FIX: http://plugins.jquery.com/node/1495
173 | // Clear identifying properties from clones
174 | if(slave_count>0) slave.id = slave.name = '';
175 |
176 | // Define element's ID and name (upload components need this!)
177 | //slave.id = slave.id || MultiFile.generateID(slave_count);
178 | if(slave_count>0) slave.id = MultiFile.generateID(slave_count);
179 | //FIX for: http://code.google.com/p/jquery-multifile-plugin/issues/detail?id=23
180 |
181 | // 2008-Apr-29: New customizable naming convention (see url below)
182 | // http://groups.google.com/group/jquery-dev/browse_frm/thread/765c73e41b34f924#
183 | slave.name = String(MultiFile.namePattern
184 | /*master name*/.replace(/\$name/gi,$(MultiFile.clone).attr('name'))
185 | /*master id */.replace(/\$id/gi, $(MultiFile.clone).attr('id'))
186 | /*group count*/.replace(/\$g/gi, group_count)//(group_count>0?group_count:''))
187 | /*slave count*/.replace(/\$i/gi, slave_count)//(slave_count>0?slave_count:''))
188 | );
189 |
190 | // If we've reached maximum number, disable input slave
191 | if( (MultiFile.max > 0) && ((MultiFile.n-1) > (MultiFile.max)) )//{ // MultiFile.n Starts at 1, so subtract 1 to find true count
192 | slave.disabled = true;
193 | //};
194 |
195 | // Remember most recent slave
196 | MultiFile.current = MultiFile.slaves[slave_count] = slave;
197 |
198 | // We'll use jQuery from now on
199 | slave = $(slave);
200 |
201 | // Clear value
202 | slave.val('').attr('value','')[0].value = '';
203 |
204 | // Stop plugin initializing on slaves
205 | slave.addClass('MultiFile-applied');
206 |
207 | // Triggered when a file is selected
208 | slave.change(function(){
209 | //if(window.console) console.log('MultiFile.slave.change',slave_count);
210 |
211 | // Lose focus to stop IE7 firing onchange again
212 | $(this).blur();
213 |
214 | //# Trigger Event! onFileSelect
215 | if(!MultiFile.trigger('onFileSelect', this, MultiFile)) return false;
216 | //# End Event!
217 |
218 | //# Retrive value of selected file from element
219 | var ERROR = '', v = String(this.value || ''/*.attr('value)*/);
220 |
221 | // check extension
222 | if(MultiFile.accept && v && !v.match(MultiFile.rxAccept))//{
223 | ERROR = MultiFile.STRING.denied.replace('$ext', String(v.match(/\.\w{1,4}$/gi)));
224 | //}
225 | //};
226 |
227 | // Disallow duplicates
228 | for(var f in MultiFile.slaves)//{
229 | if(MultiFile.slaves[f] && MultiFile.slaves[f]!=this)//{
230 | //console.log(MultiFile.slaves[f],MultiFile.slaves[f].value);
231 | if(MultiFile.slaves[f].value==v)//{
232 | ERROR = MultiFile.STRING.duplicate.replace('$file', v.match(/[^\/\\]+$/gi));
233 | //};
234 | //};
235 | //};
236 |
237 | // Create a new file input element
238 | var newEle = $(MultiFile.clone).clone();// Copy parent attributes - Thanks to Jonas Wagner
239 | //# Let's remember which input we've generated so
240 | // we can disable the empty ones before submission
241 | // See: http://plugins.jquery.com/node/1495
242 | newEle.addClass('MultiFile');
243 |
244 | // Handle error
245 | if(ERROR!=''){
246 | // Handle error
247 | MultiFile.error(ERROR);
248 |
249 | // 2007-06-24: BUG FIX - Thanks to Adrian Wróbel
250 | // Ditch the trouble maker and add a fresh new element
251 | MultiFile.n--;
252 | MultiFile.addSlave(newEle[0], slave_count);
253 | slave.parent().prepend(newEle);
254 | slave.remove();
255 | return false;
256 | };
257 |
258 | // Hide this element (NB: display:none is evil!)
259 | $(this).css({ position:'absolute', top: '-3000px' });
260 |
261 | // Add new element to the form
262 | slave.after(newEle);
263 |
264 | // Update list
265 | MultiFile.addToList( this, slave_count );
266 |
267 | // Bind functionality
268 | MultiFile.addSlave( newEle[0], slave_count+1 );
269 |
270 | //# Trigger Event! afterFileSelect
271 | if(!MultiFile.trigger('afterFileSelect', this, MultiFile)) return false;
272 | //# End Event!
273 |
274 | }); // slave.change()
275 |
276 | // Save control to element
277 | $(slave).data('MultiFile', MultiFile);
278 |
279 | };// MultiFile.addSlave
280 | // Bind a new element
281 |
282 |
283 |
284 | // Add a new file to the list
285 | MultiFile.addToList = function( slave, slave_count ){
286 | //if(window.console) console.log('MultiFile.addToList',slave_count);
287 |
288 | //# Trigger Event! onFileAppend
289 | if(!MultiFile.trigger('onFileAppend', slave, MultiFile)) return false;
290 | //# End Event!
291 |
292 | // Create label elements
293 | var
294 | r = $(''),
295 | v = String(slave.value || ''/*.attr('value)*/),
296 | a = $(''+MultiFile.STRING.file.replace('$file', v.match(/[^\/\\]+$/gi)[0])+''),
297 | b = $(''+MultiFile.STRING.remove+'');
298 |
299 | // Insert label
300 | MultiFile.list.append(
301 | r.append(b, ' ', a)
302 | );
303 |
304 | b
305 | .click(function(){
306 |
307 | //# Trigger Event! onFileRemove
308 | if(!MultiFile.trigger('onFileRemove', slave, MultiFile)) return false;
309 | //# End Event!
310 |
311 | MultiFile.n--;
312 | MultiFile.current.disabled = false;
313 |
314 | // Remove element, remove label, point to current
315 | MultiFile.slaves[slave_count] = null;
316 | $(slave).remove();
317 | $(this).parent().remove();
318 |
319 | // Show most current element again (move into view) and clear selection
320 | $(MultiFile.current).css({ position:'', top: '' });
321 | $(MultiFile.current).reset().val('').attr('value', '')[0].value = '';
322 |
323 | //# Trigger Event! afterFileRemove
324 | if(!MultiFile.trigger('afterFileRemove', slave, MultiFile)) return false;
325 | //# End Event!
326 |
327 | return false;
328 | });
329 |
330 | //# Trigger Event! afterFileAppend
331 | if(!MultiFile.trigger('afterFileAppend', slave, MultiFile)) return false;
332 | //# End Event!
333 |
334 | }; // MultiFile.addToList
335 | // Add element to selected files list
336 |
337 |
338 |
339 | // Bind functionality to the first element
340 | if(!MultiFile.MultiFile) MultiFile.addSlave(MultiFile.e, 0);
341 |
342 | // Increment control count
343 | //MultiFile.I++; // using window.MultiFile
344 | MultiFile.n++;
345 |
346 | // Save control to element
347 | MultiFile.E.data('MultiFile', MultiFile);
348 |
349 |
350 | //#####################################################################
351 | // MAIN PLUGIN FUNCTIONALITY - END
352 | //#####################################################################
353 | }); // each element
354 | };
355 |
356 | /*--------------------------------------------------------*/
357 |
358 | /*
359 | ### Core functionality and API ###
360 | */
361 | $.extend($.fn.MultiFile, {
362 | /**
363 | * This method removes all selected files
364 | *
365 | * Returns a jQuery collection of all affected elements.
366 | *
367 | * @name reset
368 | * @type jQuery
369 | * @cat Plugins/MultiFile
370 | * @author Diego A. (http://www.fyneworks.com/)
371 | *
372 | * @example $.fn.MultiFile.reset();
373 | */
374 | reset: function(){
375 | var settings = $(this).data('MultiFile');
376 | //if(settings) settings.wrapper.find('a.MultiFile-remove').click();
377 | if(settings) settings.list.find('a.MultiFile-remove').click();
378 | return $(this);
379 | },
380 |
381 |
382 | /**
383 | * This utility makes it easy to disable all 'empty' file elements in the document before submitting a form.
384 | * It marks the affected elements so they can be easily re-enabled after the form submission or validation.
385 | *
386 | * Returns a jQuery collection of all affected elements.
387 | *
388 | * @name disableEmpty
389 | * @type jQuery
390 | * @cat Plugins/MultiFile
391 | * @author Diego A. (http://www.fyneworks.com/)
392 | *
393 | * @example $.fn.MultiFile.disableEmpty();
394 | * @param String class (optional) A string specifying a class to be applied to all affected elements - Default: 'mfD'.
395 | */
396 | disableEmpty: function(klass){ klass = (typeof(klass)=='string'?klass:'')||'mfD';
397 | var o = [];
398 | $('input:file.MultiFile').each(function(){ if($(this).val()=='') o[o.length] = this; });
399 | return $(o).each(function(){ this.disabled = true }).addClass(klass);
400 | },
401 |
402 |
403 | /**
404 | * This method re-enables 'empty' file elements that were disabled (and marked) with the $.fn.MultiFile.disableEmpty method.
405 | *
406 | * Returns a jQuery collection of all affected elements.
407 | *
408 | * @name reEnableEmpty
409 | * @type jQuery
410 | * @cat Plugins/MultiFile
411 | * @author Diego A. (http://www.fyneworks.com/)
412 | *
413 | * @example $.fn.MultiFile.reEnableEmpty();
414 | * @param String klass (optional) A string specifying the class that was used to mark affected elements - Default: 'mfD'.
415 | */
416 | reEnableEmpty: function(klass){ klass = (typeof(klass)=='string'?klass:'')||'mfD';
417 | return $('input:file.'+klass).removeClass(klass).each(function(){ this.disabled = false });
418 | },
419 |
420 |
421 | /**
422 | * This method will intercept other jQuery plugins and disable empty file input elements prior to form submission
423 | *
424 |
425 | * @name intercept
426 | * @cat Plugins/MultiFile
427 | * @author Diego A. (http://www.fyneworks.com/)
428 | *
429 | * @example $.fn.MultiFile.intercept();
430 | * @param Array methods (optional) Array of method names to be intercepted
431 | */
432 | intercepted: {},
433 | intercept: function(methods, context, args){
434 | var method, value; args = args || [];
435 | if(args.constructor.toString().indexOf("Array")<0) args = [ args ];
436 | if(typeof(methods)=='function'){
437 | $.fn.MultiFile.disableEmpty();
438 | value = methods.apply(context || window, args);
439 | //SEE-http://code.google.com/p/jquery-multifile-plugin/issues/detail?id=27
440 | setTimeout(function(){ $.fn.MultiFile.reEnableEmpty() },1000);
441 | return value;
442 | };
443 | if(methods.constructor.toString().indexOf("Array")<0) methods = [methods];
444 | for(var i=0;i'),
495 | css: {
496 | border:'none', padding:'15px', size:'12.0pt',
497 | backgroundColor:'#900', color:'#fff',
498 | opacity:'.8','-webkit-border-radius': '10px','-moz-border-radius': '10px'
499 | }
500 | });
501 | window.setTimeout($.unblockUI, 2000);
502 | }
503 | else//{// save a byte!
504 | */
505 | alert(s);
506 | //}// save a byte!
507 | }
508 | }; //} });
509 |
510 | /*--------------------------------------------------------*/
511 |
512 | /*
513 | ### Additional Methods ###
514 | Required functionality outside the plugin's scope
515 | */
516 |
517 | // Native input reset method - because this alone doesn't always work: $(element).val('').attr('value', '')[0].value = '';
518 | $.fn.reset = function(){ return this.each(function(){ try{ this.reset(); }catch(e){} }); };
519 |
520 | /*--------------------------------------------------------*/
521 |
522 | /*
523 | ### Default implementation ###
524 | The plugin will attach itself to file inputs
525 | with the class 'multi' when the page loads
526 | */
527 | $(function(){
528 | //$("input:file.multi").MultiFile();
529 | $("input[type=file].multi").MultiFile();
530 | });
531 |
532 |
533 |
534 | /*# AVOID COLLISIONS #*/
535 | })(jQuery);
536 | /*# AVOID COLLISIONS #*/
537 |
--------------------------------------------------------------------------------