1 (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2 (function(root, factory) {
5 // AMDJS module definition
6 if ( typeof define === 'function' && define.amd && define.amd.jQuery ) {
7 define(['jquery'], function($) {
8 return factory($, root);
11 // CommonJS module definition
12 } else if ( typeof exports === 'object') {
14 // NOTE: To use Mockjax as a Node module you MUST provide the factory with
15 // a valid version of jQuery and a window object (the global scope):
16 // var mockjax = require('jquery.mockjax')(jQuery, window);
18 module.exports = factory;
20 // Global jQuery in web browsers
22 return factory(root.jQuery || root.$, root);
24 }(this, function($, window) {
30 unmockedAjaxCalls = [],
31 CALLBACK_REGEX = /=\?(&|$)/,
32 jsc = (new Date()).getTime(),
33 DEFAULT_RESPONSE_TIME = 500;
35 // Parse the given XML string.
36 function parseXML(xml) {
37 if ( window.DOMParser === undefined && window.ActiveXObject ) {
38 window.DOMParser = function() { };
39 DOMParser.prototype.parseFromString = function( xmlString ) {
40 var doc = new ActiveXObject('Microsoft.XMLDOM');
42 doc.loadXML( xmlString );
48 var xmlDoc = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
49 if ( $.isXMLDoc( xmlDoc ) ) {
50 var err = $('parsererror', xmlDoc);
51 if ( err.length === 1 ) {
52 throw new Error('Error: ' + $(xmlDoc).text() );
55 throw new Error('Unable to parse XML');
59 var msg = ( e.name === undefined ? e : e.name + ': ' + e.message );
60 $(document).trigger('xmlParseError', [ msg ]);
65 // Check if the data field on the mock handler and the request match. This
66 // can be used to restrict a mock handler to being used only when a certain
67 // set of data is passed to it.
68 function isMockDataEqual( mock, live ) {
69 logger.debug( mock, ['Checking mock data against request data', mock, live] );
72 if ( $.isFunction(mock) ) {
76 // Test for situations where the data is a querystring (not an object)
77 if (typeof live === 'string') {
78 // Querystring may be a regex
79 if ($.isFunction( mock.test )) {
80 return mock.test(live);
81 } else if (typeof mock === 'object') {
82 live = getQueryParams(live);
88 $.each(mock, function(k) {
89 if ( live[k] === undefined ) {
93 if ( typeof live[k] === 'object' && live[k] !== null ) {
94 if ( identical && $.isArray( live[k] ) ) {
95 identical = $.isArray( mock[k] ) && live[k].length === mock[k].length;
97 identical = identical && isMockDataEqual(mock[k], live[k]);
99 if ( mock[k] && $.isFunction( mock[k].test ) ) {
100 identical = identical && mock[k].test(live[k]);
102 identical = identical && ( mock[k] === live[k] );
111 function getQueryParams(queryString) {
112 var i, l, param, tmp,
114 params = String(queryString).split(/&/);
116 for (i=0, l=params.length; i<l; ++i) {
119 param = decodeURIComponent(param.replace(/\+/g, ' '));
120 param = param.split(/=/);
122 // Can't parse this one, so let it go?
126 if (paramsObj[param[0]]) {
127 // this is an array query param (more than one entry in query)
128 if (!paramsObj[param[0]].splice) {
129 // if not already an array, make it one
130 tmp = paramsObj[param[0]];
131 paramsObj[param[0]] = [];
132 paramsObj[param[0]].push(tmp);
134 paramsObj[param[0]].push(param[1]);
136 paramsObj[param[0]] = param[1];
140 logger.debug( null, ['Getting query params from string', queryString, paramsObj] );
145 // See if a mock handler property matches the default settings
146 function isDefaultSetting(handler, property) {
147 return handler[property] === $.mockjaxSettings[property];
150 // Check the given handler should mock the given request
151 function getMockForRequest( handler, requestSettings ) {
152 // If the mock was registered with a function, let the function decide if we
153 // want to mock this request
154 if ( $.isFunction(handler) ) {
155 return handler( requestSettings );
158 // Inspect the URL of the request and check if the mock handler's url
159 // matches the url for this ajax request
160 if ( $.isFunction(handler.url.test) ) {
161 // The user provided a regex for the url, test it
162 if ( !handler.url.test( requestSettings.url ) ) {
167 // Apply namespace prefix to the mock handler's url.
168 var namespace = handler.namespace || $.mockjaxSettings.namespace;
170 var namespacedUrl = [namespace, handler.url].join('/');
171 namespacedUrl = namespacedUrl.replace(/(\/+)/g, '/');
172 handler.url = namespacedUrl;
175 // Look for a simple wildcard '*' or a direct URL match
176 var star = handler.url.indexOf('*');
177 if (handler.url !== requestSettings.url && star === -1 ||
178 !new RegExp(handler.url.replace(/[-[\]{}()+?.,\\^$|#\s]/g, '\\$&').replace(/\*/g, '.+')).test(requestSettings.url)) {
183 // Inspect the request headers submitted
184 if ( handler.requestHeaders ) {
185 //No expectation for headers, do not mock this request
186 if (requestSettings.headers === undefined) {
189 var headersMismatch = false;
190 $.each(handler.requestHeaders, function(key, value) {
191 var v = requestSettings.headers[key];
193 headersMismatch = true;
197 //Headers do not match, do not mock this request
198 if (headersMismatch) {
204 // Inspect the data submitted in the request (either POST body or GET query string)
205 if ( handler.data ) {
206 if ( !requestSettings.data || !isMockDataEqual(handler.data, requestSettings.data) ) {
207 // They're not identical, do not mock this request
211 // Inspect the request type
212 if ( handler && handler.type &&
213 handler.type.toLowerCase() !== requestSettings.type.toLowerCase() ) {
214 // The request type doesn't match (GET vs. POST)
221 function isPosNum(value) {
222 return typeof value === 'number' && value >= 0;
225 function parseResponseTimeOpt(responseTime) {
226 if ($.isArray(responseTime) && responseTime.length === 2) {
227 var min = responseTime[0];
228 var max = responseTime[1];
229 if(isPosNum(min) && isPosNum(max)) {
230 return Math.floor(Math.random() * (max - min)) + min;
232 } else if(isPosNum(responseTime)) {
235 return DEFAULT_RESPONSE_TIME;
238 // Process the xhr objects send operation
239 function _xhrSend(mockHandler, requestSettings, origSettings) {
240 logger.debug( mockHandler, ['Sending fake XHR request', mockHandler, requestSettings, origSettings] );
242 // This is a substitute for < 1.4 which lacks $.proxy
243 var process = (function(that) {
246 // The request has returned
247 this.status = mockHandler.status;
248 this.statusText = mockHandler.statusText;
251 var finishRequest = function () {
255 // Copy over our mock to our xhr object before passing control back to
256 // jQuery's onreadystatechange callback
257 if ( requestSettings.dataType === 'json' && ( typeof mockHandler.responseText === 'object' ) ) {
258 this.responseText = JSON.stringify(mockHandler.responseText);
259 } else if ( requestSettings.dataType === 'xml' ) {
260 if ( typeof mockHandler.responseXML === 'string' ) {
261 this.responseXML = parseXML(mockHandler.responseXML);
262 //in jQuery 1.9.1+, responseXML is processed differently and relies on responseText
263 this.responseText = mockHandler.responseXML;
265 this.responseXML = mockHandler.responseXML;
267 } else if (typeof mockHandler.responseText === 'object' && mockHandler.responseText !== null) {
268 // since jQuery 1.9 responseText type has to match contentType
269 mockHandler.contentType = 'application/json';
270 this.responseText = JSON.stringify(mockHandler.responseText);
272 this.responseText = mockHandler.responseText;
274 if( typeof mockHandler.status === 'number' || typeof mockHandler.status === 'string' ) {
275 this.status = mockHandler.status;
277 if( typeof mockHandler.statusText === 'string') {
278 this.statusText = mockHandler.statusText;
280 // jQuery 2.0 renamed onreadystatechange to onload
281 onReady = this.onload || this.onreadystatechange;
283 // jQuery < 1.4 doesn't have onreadystate change for xhr
284 if ( $.isFunction( onReady ) ) {
285 if( mockHandler.isTimeout) {
288 onReady.call( this, mockHandler.isTimeout ? 'timeout' : undefined );
289 } else if ( mockHandler.isTimeout ) {
290 // Fix for 1.3.2 timeout to keep success from firing.
295 // We have an executable function, call it to give
296 // the mock handler a chance to update it's data
297 if ( $.isFunction(mockHandler.response) ) {
298 // Wait for it to finish
299 if ( mockHandler.response.length === 2 ) {
300 mockHandler.response(origSettings, function () {
301 finishRequest.call(that);
305 mockHandler.response(origSettings);
309 finishRequest.call(that);
314 if ( mockHandler.proxy ) {
315 logger.info( mockHandler, ['Retrieving proxy file: ' + mockHandler.proxy, mockHandler] );
316 // We're proxying this request and loading in an external file instead
319 url: mockHandler.proxy,
320 type: mockHandler.proxyType,
321 data: mockHandler.data,
322 async: requestSettings.async,
323 dataType: requestSettings.dataType === 'script' ? 'text/plain' : requestSettings.dataType,
324 complete: function(xhr) {
326 // jQuery will convert the text to XML for us, and if we use the actual responseXML here
327 // then some other things don't happen, resulting in no data given to the 'success' cb
328 mockHandler.responseXML = mockHandler.responseText = xhr.responseText;
330 // Don't override the handler status/statusText if it's specified by the config
331 if (isDefaultSetting(mockHandler, 'status')) {
332 mockHandler.status = xhr.status;
334 if (isDefaultSetting(mockHandler, 'statusText')) {
335 mockHandler.statusText = xhr.statusText;
338 if ( requestSettings.async === false ) {
339 // TODO: Blocking delay
342 this.responseTimer = setTimeout(process, parseResponseTimeOpt(mockHandler.responseTime));
347 // type === 'POST' || 'GET' || 'DELETE'
348 if ( requestSettings.async === false ) {
349 // TODO: Blocking delay
352 this.responseTimer = setTimeout(process, parseResponseTimeOpt(mockHandler.responseTime));
358 // Construct a mocked XHR Object
359 function xhr(mockHandler, requestSettings, origSettings, origHandler) {
360 logger.debug( mockHandler, ['Creating new mock XHR object', mockHandler, requestSettings, origSettings, origHandler] );
362 // Extend with our default mockjax settings
363 mockHandler = $.extend(true, {}, $.mockjaxSettings, mockHandler);
365 if (typeof mockHandler.headers === 'undefined') {
366 mockHandler.headers = {};
368 if (typeof requestSettings.headers === 'undefined') {
369 requestSettings.headers = {};
371 if ( mockHandler.contentType ) {
372 mockHandler.headers['content-type'] = mockHandler.contentType;
376 status: mockHandler.status,
377 statusText: mockHandler.statusText,
379 open: function() { },
381 origHandler.fired = true;
382 _xhrSend.call(this, mockHandler, requestSettings, origSettings);
385 clearTimeout(this.responseTimer);
387 setRequestHeader: function(header, value) {
388 requestSettings.headers[header] = value;
390 getResponseHeader: function(header) {
391 // 'Last-modified', 'Etag', 'content-type' are all checked by jQuery
392 if ( mockHandler.headers && mockHandler.headers[header] ) {
393 // Return arbitrary headers
394 return mockHandler.headers[header];
395 } else if ( header.toLowerCase() === 'last-modified' ) {
396 return mockHandler.lastModified || (new Date()).toString();
397 } else if ( header.toLowerCase() === 'etag' ) {
398 return mockHandler.etag || '';
399 } else if ( header.toLowerCase() === 'content-type' ) {
400 return mockHandler.contentType || 'text/plain';
403 getAllResponseHeaders: function() {
405 // since jQuery 1.9 responseText type has to match contentType
406 if (mockHandler.contentType) {
407 mockHandler.headers['Content-Type'] = mockHandler.contentType;
409 $.each(mockHandler.headers, function(k, v) {
410 headers += k + ': ' + v + '\n';
417 // Process a JSONP mock request.
418 function processJsonpMock( requestSettings, mockHandler, origSettings ) {
419 // Handle JSONP Parameter Callbacks, we need to replicate some of the jQuery core here
420 // because there isn't an easy hook for the cross domain script tag of jsonp
422 processJsonpUrl( requestSettings );
424 requestSettings.dataType = 'json';
425 if(requestSettings.data && CALLBACK_REGEX.test(requestSettings.data) || CALLBACK_REGEX.test(requestSettings.url)) {
426 createJsonpCallback(requestSettings, mockHandler, origSettings);
428 // We need to make sure
429 // that a JSONP style response is executed properly
431 var rurl = /^(\w+:)?\/\/([^\/?#]+)/,
432 parts = rurl.exec( requestSettings.url ),
433 remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
435 requestSettings.dataType = 'script';
436 if(requestSettings.type.toUpperCase() === 'GET' && remote ) {
437 var newMockReturn = processJsonpRequest( requestSettings, mockHandler, origSettings );
439 // Check if we are supposed to return a Deferred back to the mock call, or just
442 return newMockReturn;
451 // Append the required callback parameter to the end of the request URL, for a JSONP request
452 function processJsonpUrl( requestSettings ) {
453 if ( requestSettings.type.toUpperCase() === 'GET' ) {
454 if ( !CALLBACK_REGEX.test( requestSettings.url ) ) {
455 requestSettings.url += (/\?/.test( requestSettings.url ) ? '&' : '?') +
456 (requestSettings.jsonp || 'callback') + '=?';
458 } else if ( !requestSettings.data || !CALLBACK_REGEX.test(requestSettings.data) ) {
459 requestSettings.data = (requestSettings.data ? requestSettings.data + '&' : '') + (requestSettings.jsonp || 'callback') + '=?';
463 // Process a JSONP request by evaluating the mocked response text
464 function processJsonpRequest( requestSettings, mockHandler, origSettings ) {
465 logger.debug( mockHandler, ['Performing JSONP request', mockHandler, requestSettings, origSettings] );
467 // Synthesize the mock request for adding a script tag
468 var callbackContext = origSettings && origSettings.context || requestSettings,
469 // If we are running under jQuery 1.5+, return a deferred object
470 newMock = ($.Deferred) ? (new $.Deferred()) : null;
472 // If the response handler on the moock is a function, call it
473 if ( mockHandler.response && $.isFunction(mockHandler.response) ) {
475 mockHandler.response(origSettings);
478 } else if ( typeof mockHandler.responseText === 'object' ) {
479 // Evaluate the responseText javascript in a global context
480 $.globalEval( '(' + JSON.stringify( mockHandler.responseText ) + ')');
482 } else if (mockHandler.proxy) {
483 logger.info( mockHandler, ['Performing JSONP proxy request: ' + mockHandler.proxy, mockHandler] );
485 // This handles the unique case where we have a remote URL, but want to proxy the JSONP
486 // response to another file (not the same URL as the mock matching)
489 url: mockHandler.proxy,
490 type: mockHandler.proxyType,
491 data: mockHandler.data,
492 dataType: requestSettings.dataType === 'script' ? 'text/plain' : requestSettings.dataType,
493 complete: function(xhr) {
494 $.globalEval( '(' + xhr.responseText + ')');
495 completeJsonpCall( requestSettings, mockHandler, callbackContext, newMock );
503 ((typeof mockHandler.responseText === 'string') ?
504 ('"' + mockHandler.responseText + '"') : mockHandler.responseText) +
508 completeJsonpCall( requestSettings, mockHandler, callbackContext, newMock );
513 function completeJsonpCall( requestSettings, mockHandler, callbackContext, newMock ) {
516 // Successful response
517 setTimeout(function() {
518 jsonpSuccess( requestSettings, callbackContext, mockHandler );
519 jsonpComplete( requestSettings, callbackContext );
523 json = $.parseJSON( mockHandler.responseText );
524 } catch (err) { /* just checking... */ }
526 newMock.resolveWith( callbackContext, [json || mockHandler.responseText] );
527 logger.log( mockHandler, ['JSONP mock call complete', mockHandler, newMock] );
529 }, parseResponseTimeOpt( mockHandler.responseTime ));
533 // Create the required JSONP callback function for the request
534 function createJsonpCallback( requestSettings, mockHandler, origSettings ) {
535 var callbackContext = origSettings && origSettings.context || requestSettings;
536 var jsonp = (typeof requestSettings.jsonpCallback === 'string' && requestSettings.jsonpCallback) || ('jsonp' + jsc++);
538 // Replace the =? sequence both in the query string and the data
539 if ( requestSettings.data ) {
540 requestSettings.data = (requestSettings.data + '').replace(CALLBACK_REGEX, '=' + jsonp + '$1');
543 requestSettings.url = requestSettings.url.replace(CALLBACK_REGEX, '=' + jsonp + '$1');
546 // Handle JSONP-style loading
547 window[ jsonp ] = window[ jsonp ] || function() {
548 jsonpSuccess( requestSettings, callbackContext, mockHandler );
549 jsonpComplete( requestSettings, callbackContext );
551 window[ jsonp ] = undefined;
554 delete window[ jsonp ];
557 requestSettings.jsonpCallback = jsonp;
560 // The JSONP request was successful
561 function jsonpSuccess(requestSettings, callbackContext, mockHandler) {
562 // If a local callback was specified, fire it and pass it the data
563 if ( requestSettings.success ) {
564 requestSettings.success.call( callbackContext, mockHandler.responseText || '', 'success', {} );
567 // Fire the global callback
568 if ( requestSettings.global ) {
569 (requestSettings.context ? $(requestSettings.context) : $.event).trigger('ajaxSuccess', [{}, requestSettings]);
573 // The JSONP request was completed
574 function jsonpComplete(requestSettings, callbackContext) {
575 if ( requestSettings.complete ) {
576 requestSettings.complete.call( callbackContext, {
577 statusText: 'success',
582 // The request was completed
583 if ( requestSettings.global ) {
584 (requestSettings.context ? $(requestSettings.context) : $.event).trigger('ajaxComplete', [{}, requestSettings]);
587 // Handle the global AJAX counter
588 if ( requestSettings.global && ! --$.active ) {
589 $.event.trigger( 'ajaxStop' );
594 // The core $.ajax replacement.
595 function handleAjax( url, origSettings ) {
596 var mockRequest, requestSettings, mockHandler, overrideCallback;
598 logger.debug( null, ['Ajax call intercepted', url, origSettings] );
600 // If url is an object, simulate pre-1.5 signature
601 if ( typeof url === 'object' ) {
605 // work around to support 1.5 signature
606 origSettings = origSettings || {};
607 origSettings.url = url || origSettings.url;
610 // Extend the original settings for the request
611 requestSettings = $.ajaxSetup({}, origSettings);
612 requestSettings.type = requestSettings.method = requestSettings.method || requestSettings.type;
614 // Generic function to override callback methods for use with
615 // callback options (onAfterSuccess, onAfterError, onAfterComplete)
616 overrideCallback = function(action, mockHandler) {
617 var origHandler = origSettings[action.toLowerCase()];
619 if ( $.isFunction(origHandler) ) {
620 origHandler.apply(this, [].slice.call(arguments));
622 mockHandler['onAfter' + action]();
626 // Iterate over our mock handlers (in registration order) until we find
627 // one that is willing to intercept the request
628 for(var k = 0; k < mockHandlers.length; k++) {
629 if ( !mockHandlers[k] ) {
633 mockHandler = getMockForRequest( mockHandlers[k], requestSettings );
635 logger.debug( mockHandlers[k], ['Mock does not match request', url, requestSettings] );
636 // No valid mock found for this request
640 if ($.mockjaxSettings.retainAjaxCalls) {
641 mockedAjaxCalls.push(requestSettings);
644 // If logging is enabled, log the mock to the console
645 logger.info( mockHandler, [
646 'MOCK ' + requestSettings.type.toUpperCase() + ': ' + requestSettings.url,
647 $.ajaxSetup({}, requestSettings)
651 if ( requestSettings.dataType && requestSettings.dataType.toUpperCase() === 'JSONP' ) {
652 if ((mockRequest = processJsonpMock( requestSettings, mockHandler, origSettings ))) {
653 // This mock will handle the JSONP request
658 // We are mocking, so there will be no cross domain request, however, jQuery
659 // aggressively pursues this if the domains don't match, so we need to
660 // explicitly disallow it. (See #136)
661 origSettings.crossDomain = false;
663 // Removed to fix #54 - keep the mocking data object intact
664 //mockHandler.data = requestSettings.data;
666 mockHandler.cache = requestSettings.cache;
667 mockHandler.timeout = requestSettings.timeout;
668 mockHandler.global = requestSettings.global;
670 // In the case of a timeout, we just need to ensure
671 // an actual jQuery timeout (That is, our reponse won't)
672 // return faster than the timeout setting.
673 if ( mockHandler.isTimeout ) {
674 if ( mockHandler.responseTime > 1 ) {
675 origSettings.timeout = mockHandler.responseTime - 1;
677 mockHandler.responseTime = 2;
678 origSettings.timeout = 1;
682 // Set up onAfter[X] callback functions
683 if ( $.isFunction( mockHandler.onAfterSuccess ) ) {
684 origSettings.success = overrideCallback('Success', mockHandler);
686 if ( $.isFunction( mockHandler.onAfterError ) ) {
687 origSettings.error = overrideCallback('Error', mockHandler);
689 if ( $.isFunction( mockHandler.onAfterComplete ) ) {
690 origSettings.complete = overrideCallback('Complete', mockHandler);
693 copyUrlParameters(mockHandler, origSettings);
695 /* jshint loopfunc:true */
696 (function(mockHandler, requestSettings, origSettings, origHandler) {
698 mockRequest = _ajax.call($, $.extend(true, {}, origSettings, {
699 // Mock the XHR object
700 xhr: function() { return xhr( mockHandler, requestSettings, origSettings, origHandler ); }
702 })(mockHandler, requestSettings, origSettings, mockHandlers[k]);
703 /* jshint loopfunc:false */
708 // We don't have a mock request
709 logger.log( null, ['No mock matched to request', url, origSettings] );
710 if ($.mockjaxSettings.retainAjaxCalls) {
711 unmockedAjaxCalls.push(origSettings);
713 if($.mockjaxSettings.throwUnmocked === true) {
714 throw new Error('AJAX not mocked: ' + origSettings.url);
716 else { // trigger a normal request
717 return _ajax.apply($, [origSettings]);
722 * Copies URL parameter values if they were captured by a regular expression
723 * @param {Object} mockHandler
724 * @param {Object} origSettings
726 function copyUrlParameters(mockHandler, origSettings) {
727 //parameters aren't captured if the URL isn't a RegExp
728 if (!(mockHandler.url instanceof RegExp)) {
731 //if no URL params were defined on the handler, don't attempt a capture
732 if (!mockHandler.hasOwnProperty('urlParams')) {
735 var captures = mockHandler.url.exec(origSettings.url);
736 //the whole RegExp match is always the first value in the capture results
737 if (captures.length === 1) {
741 //use handler params as keys and capture resuts as values
743 capturesLength = captures.length,
744 paramsLength = mockHandler.urlParams.length,
745 //in case the number of params specified is less than actual captures
746 maxIterations = Math.min(capturesLength, paramsLength),
748 for (i; i < maxIterations; i++) {
749 var key = mockHandler.urlParams[i];
750 paramValues[key] = captures[i];
752 origSettings.urlParams = paramValues;
756 * Clears handlers that mock given url
760 function clearByUrl(url) {
764 match=url instanceof RegExp ?
765 function(testUrl) { return url.test(testUrl); } :
766 function(testUrl) { return url === testUrl; };
767 for (i=0, len=mockHandlers.length; i<len; i++) {
768 handler = mockHandlers[i];
769 if (!match(handler.url)) {
770 results.push(handler);
772 logger.log( handler, [
773 'Clearing mock: ' + (handler && handler.url),
789 _log: function logger( mockHandler, args, level ) {
790 var loggerLevel = $.mockjaxSettings.logging;
791 if (mockHandler && typeof mockHandler.logging !== 'undefined') {
792 loggerLevel = mockHandler.logging;
794 level = ( level === 0 ) ? level : ( level || logLevels.LOG );
795 args = (args.splice) ? args : [ args ];
797 // Is logging turned off for this mock or mockjax as a whole?
798 // Or is this log message above the desired log level?
799 if ( loggerLevel === false || loggerLevel < level ) {
803 if ( $.mockjaxSettings.log ) {
804 return $.mockjaxSettings.log( mockHandler, args[1] || args[0] );
805 } else if ( $.mockjaxSettings.logger && $.mockjaxSettings.logger[$.mockjaxSettings.logLevelMethods[level]] ) {
806 return $.mockjaxSettings.logger[$.mockjaxSettings.logLevelMethods[level]].apply( $.mockjaxSettings.logger, args );
810 * Convenience method for logging a DEBUG level message
811 * @param {Object} m The mock handler in question
812 * @param {Array|String|Object} a The items to log
813 * @return {?} Will return whatever the $.mockjaxSettings.logger method for this level would return (generally 'undefined')
815 debug: function(m,a) { return logger._log(m,a,logLevels.DEBUG); },
819 log: function(m,a) { return logger._log(m,a,logLevels.LOG); },
823 info: function(m,a) { return logger._log(m,a,logLevels.INFO); },
827 warn: function(m,a) { return logger._log(m,a,logLevels.WARN); },
831 error: function(m,a) { return logger._log(m,a,logLevels.ERROR); }
843 * Default settings for mockjax. Some of these are used for defaults of
844 * individual mock handlers, and some are for the library as a whole.
845 * For individual mock handler settings, please see the README on the repo:
846 * https://github.com/jakerella/jquery-mockjax#api-methods
850 $.mockjaxSettings = {
851 log: null, // this is only here for historical purposes... use $.mockjaxSettings.logger
852 logger: window.console,
854 logLevelMethods: ['error', 'warn', 'info', 'log', 'debug'],
858 responseTime: DEFAULT_RESPONSE_TIME,
860 throwUnmocked: false,
861 retainAjaxCalls: true,
862 contentType: 'text/plain',
872 etag: 'IJF@H#@923uf8023hFO@I#H#',
873 'content-type' : 'text/plain'
878 * Create a new mock Ajax handler. When a mock handler is matched during a
879 * $.ajax() call this library will intercept that request and fake a response
880 * using the data and methods in the mock. You can see all settings in the
881 * README of the main repository:
882 * https://github.com/jakerella/jquery-mockjax#api-methods
884 * @param {Object} settings The mock handelr settings: https://github.com/jakerella/jquery-mockjax#api-methods
885 * @return {Number} The id (index) of the mock handler suitable for clearing (see $.mockjax.clear())
887 $.mockjax = function(settings) {
889 if ( $.isArray(settings) ) {
890 return $.map(settings, function(s) {
895 var i = mockHandlers.length;
896 mockHandlers[i] = settings;
897 logger.log( settings, ['Created new mock handler', settings] );
901 $.mockjax._logger = logger;
904 * Remove an Ajax mock from those held in memory. This will prevent any
905 * future Ajax request mocking for matched requests.
906 * NOTE: Clearing a mock will not prevent the resolution of in progress requests
908 * @param {Number|String|RegExp} i OPTIONAL The mock to clear. If not provided, all mocks are cleared,
909 * if a number it is the index in the in-memory cache. If a string or
910 * RegExp, find a mock that matches that URL and clear it.
913 $.mockjax.clear = function(i) {
914 if ( typeof i === 'string' || i instanceof RegExp) {
915 mockHandlers = clearByUrl(i);
916 } else if ( i || i === 0 ) {
917 logger.log( mockHandlers[i], [
918 'Clearing mock: ' + (mockHandlers[i] && mockHandlers[i].url),
921 mockHandlers[i] = null;
923 logger.log( null, 'Clearing all mocks' );
926 mockedAjaxCalls = [];
927 unmockedAjaxCalls = [];
931 * By default all Ajax requests performed after loading Mockjax are recorded
932 * so that we can see which requests were mocked and which were not. This
933 * method allows the developer to clear those retained requests.
937 $.mockjax.clearRetainedAjaxCalls = function() {
938 mockedAjaxCalls = [];
939 unmockedAjaxCalls = [];
940 logger.debug( null, 'Cleared retained ajax calls' );
944 * Retrive the mock handler with the given id (index).
946 * @param {Number} i The id (index) to retrieve
947 * @return {Object} The mock handler settings
949 $.mockjax.handler = function(i) {
950 if ( arguments.length === 1 ) {
951 return mockHandlers[i];
956 * Retrieve all Ajax calls that have been mocked by this library during the
957 * current session (in other words, only since you last loaded this file).
959 * @return {Array} The mocked Ajax calls (request settings)
961 $.mockjax.mockedAjaxCalls = function() {
962 return mockedAjaxCalls;
966 * Return all mock handlers that have NOT been matched against Ajax requests
968 * @return {Array} The mock handlers
970 $.mockjax.unfiredHandlers = function() {
972 for (var i=0, len=mockHandlers.length; i<len; i++) {
973 var handler = mockHandlers[i];
974 if (handler !== null && !handler.fired) {
975 results.push(handler);
982 * Retrieve all Ajax calls that have NOT been mocked by this library during
983 * the current session (in other words, only since you last loaded this file).
985 * @return {Array} The mocked Ajax calls (request settings)
987 $.mockjax.unmockedAjaxCalls = function() {
988 return unmockedAjaxCalls;
995 },{}],2:[function(require,module,exports){
996 require('./test_util');
997 require('./test_tree');
998 require('./test_jqtree');
1000 QUnit.config.testTimeout = 5000;
1002 },{"./test_jqtree":3,"./test_tree":4,"./test_util":5}],3:[function(require,module,exports){
1003 var mockjax = require('jquery-mockjax')(jQuery, window);
1005 var utils_for_test = require('./utils_for_test');
1007 var example_data = utils_for_test.example_data;
1008 var example_data2 = utils_for_test.example_data2;
1009 var formatNodes = utils_for_test.formatNodes;
1010 var formatTitles = utils_for_test.formatTitles;
1011 var isNodeOpen = utils_for_test.isNodeOpen;
1012 var isNodeClosed = utils_for_test.isNodeClosed;
1014 var tree_vars = utils_for_test.getTreeVariables();
1016 var Position = tree_vars.Position;
1018 var test = QUnit.test;
1021 QUnit.module("jqtree", {
1022 beforeEach: function() {
1023 $('body').append('<div id="tree1"></div>');
1026 afterEach: function() {
1027 var $tree = $('#tree1');
1028 $tree.tree('destroy');
1035 test("create jqtree from data", function(assert) {
1041 $('#tree1').children().length, 1,
1042 'number of children on level 0'
1045 $('#tree1').children().is('ul.jqtree-tree'),
1046 'first element is ul.jqtree-tree'
1049 $('#tree1 ul.jqtree-tree > li').length, 2,
1050 'number of children on level 1'
1053 $('#tree1 ul.jqtree-tree li:eq(0)').is('li.jqtree-folder.jqtree-closed'),
1054 'first child is li.jqtree-folder.jqtree-closed'
1057 $('#tree1 ul.jqtree-tree li:eq(0) > .jqtree-element > a.jqtree-toggler').is('a.jqtree-toggler.jqtree-closed'),
1058 'button in first folder'
1061 $('#tree1 ul.jqtree-tree li:eq(0) > .jqtree-element span.jqtree-title').text(),
1066 test('toggle', function(assert) {
1068 var done = assert.async();
1071 var $tree = $('#tree1');
1082 assert.ok(! isNodeClosed($node1), 'node1 is open');
1085 $tree.tree('toggle', node1);
1092 assert.ok(isNodeClosed($node1), 'node1 is closed');
1098 var tree = $tree.tree('getTree');
1099 node1 = tree.children[0];
1100 $node1 = $tree.find('ul.jqtree-tree li:eq(0)');
1102 // node1 is initially closed
1103 assert.ok(isNodeClosed($node1), 'node1 is closed');
1106 $tree.tree('toggle', node1);
1109 test("click event", function(assert) {
1110 var select_count = 0;
1113 var $tree = $('#tree1');
1120 var $node1 = $tree.find('ul.jqtree-tree li:first');
1121 var $text_span = $node1.find('span:first');
1123 $tree.bind('tree.click', function(e) {
1124 assert.equal(e.node.name, 'node1');
1127 var done = assert.async();
1129 $tree.bind('tree.select', function(e) {
1132 if (select_count == 1) {
1133 assert.equal(e.node.name, 'node1');
1135 assert.equal($tree.tree('getSelectedNode').name, 'node1');
1141 assert.equal(e.node, null);
1142 assert.equal(e.previous_node.name, 'node1');
1143 assert.equal($tree.tree('getSelectedNode'), false);
1153 test('saveState', function(assert) {
1154 var $tree = $('#tree1');
1158 function setState(state) {
1159 saved_state = state;
1162 function getState() {
1166 function createTree() {
1170 onSetStateFromStorage: setState,
1171 onGetStateFromStorage: getState,
1179 // nodes are initially closed
1180 var tree = $tree.tree('getTree');
1181 tree.iterate(function(node) {
1182 assert.ok(! node.is_open, 'jqtree-closed');
1187 $tree.tree('toggle', tree.children[0]);
1190 assert.ok(tree.children[0].is_open, 'node1 is_open');
1193 $tree.tree('selectNode', tree.children[1]);
1195 // node2 is selected
1197 $tree.tree('getSelectedNode').name,
1199 'getSelectedNode (1)'
1202 // create tree again
1203 $tree.tree('destroy');
1206 tree = $tree.tree('getTree');
1207 assert.ok(tree.children[0].is_open, 'node1 is_open');
1208 assert.ok(! tree.children[1].is_open, 'node2 is closed');
1210 // node2 is selected
1212 $tree.tree('getSelectedNode').name,
1214 'getSelectedNode (2)'
1218 test('getSelectedNode', function(assert) {
1219 var $tree = $('#tree1');
1227 // there is no node selected
1229 $tree.tree('getSelectedNode'),
1235 var tree = $tree.tree('getTree');
1236 var node1 = tree.children[0];
1237 $tree.tree('selectNode', node1);
1239 // node1 is selected
1241 $tree.tree('getSelectedNode').name,
1247 test("toJson", function(assert) {
1249 var $tree = $('#tree1');
1256 $tree.tree('toJson'),
1257 '[{"name":"node1","id":123,"int_property":1,"str_property":"1",'+
1258 '"children":[{"name":"child1","id":125,"int_property":2},{"name":'+
1259 '"child2","id":126}]},{"name":"node2","id":124,"int_property":3,'+
1260 '"str_property":"3","children":[{"name":"child3","id":127}]}]'
1263 // Check that properties 'children', 'parent' and 'element' still exist.
1264 var tree = $tree.tree('getTree');
1265 assert.equal(tree.children.length, 2);
1266 assert.ok(tree.children[0].parent != undefined, 'parent');
1267 assert.ok($(tree.children[0].element).is('li'), 'element');
1270 test('loadData', function(assert) {
1272 var $tree = $('#tree1');
1278 // first node is 'node1'
1280 $tree.find('> ul > li:first .jqtree-element:first > span').text(),
1285 $tree.tree('loadData', example_data2);
1287 // first node is 'main'
1289 $tree.find('> ul > li:first .jqtree-element:first > span').text(),
1293 // - load new data under node 'child3'
1294 $tree.tree('loadData', example_data);
1296 var child3 = $tree.tree('getNodeByName', 'child3');
1299 { label: 'c4', id: 200 },
1301 label: 'c5', id: 201,
1303 { label: 'c6', id: 202 }
1307 $tree.tree('loadData', data, child3);
1309 // first node in html is still 'node1'
1311 $tree.find('li:eq(0)').find('.jqtree-element:eq(0) span.jqtree-title').text(),
1315 // Node 'child3' now has a children 'c4' and 'c5'
1316 var $child3 = $tree.find('span:contains(child3)');
1317 var $li = $child3.closest('li');
1319 $li.children('ul').children('li:eq(0)').find('.jqtree-element span.jqtree-title').text(),
1323 // Node 'child3' must have toggler button
1325 $child3.prev().is('a.jqtree-toggler'),
1326 "node 'child3' must have toggler button"
1329 // - select node 'c5' and load new data under 'child3'
1330 var c5 = $tree.tree('getNodeByName', 'c5');
1331 $tree.tree('selectNode', c5);
1333 assert.equal($tree.tree('getSelectedNode').name, 'c5');
1339 $tree.tree('loadData', data2, child3);
1341 // c5 must be deselected
1342 assert.equal($tree.tree('getSelectedNode'), false);
1344 // - select c7; load new data under child3; note that c7 has no id
1345 $tree.tree('selectNode', $tree.tree('getNodeByName', 'c7'));
1347 assert.equal($tree.tree('getSelectedNode').name, 'c7');
1349 $tree.tree('loadData', [ 'c9' ], child3);
1351 assert.equal($tree.tree('getSelectedNode'), false);
1353 // - select c9 (which has no id); load new nodes under child2
1354 $tree.tree('selectNode', $tree.tree('getNodeByName', 'c9'));
1356 var child2 = $tree.tree('getNodeByName', 'child2');
1357 $tree.tree('loadData', [ 'c10' ], child2);
1359 assert.equal($tree.tree('getSelectedNode').name, 'c9');
1362 test('openNode and closeNode', function(assert) {
1364 var $tree = $('#tree1');
1369 var node2 = $tree.tree('getNodeByName', 'node2');
1370 assert.equal(node2.name, 'node2');
1371 assert.equal(node2.is_open, undefined);
1374 $tree.tree('openNode', node2, false);
1375 assert.equal(node2.is_open, true);
1376 assert.equal(isNodeOpen($(node2.element)), true);
1379 $tree.tree('closeNode', node2, false);
1380 assert.equal(node2.is_open, false);
1381 assert.equal(isNodeClosed($(node2.element)), true);
1384 var node1 = $tree.tree('getNodeByName', 'node1');
1385 var child1 = $tree.tree('getNodeByName', 'child1');
1387 // add a child to child1 so it is a folder
1388 $tree.tree('appendNode', 'child1a', child1);
1390 // node1 is initialy closed
1391 assert.equal(node1.is_open, undefined);
1394 $tree.tree('openNode', child1, false);
1396 // node1 and child1 are now open1
1397 assert.equal(node1.is_open, true);
1398 assert.equal(child1.is_open, true);
1401 function test_open_node_with_callback(slide, include_slide_param, assert) {
1403 var $tree = $('#tree1');
1408 var node2 = $tree.tree('getNodeByName', 'node2');
1411 var done = assert.async();
1413 function handleOpenNode(node) {
1414 assert.equal(node.name, 'node2');
1415 assert.ok(node.is_open);
1420 if (include_slide_param) {
1421 $tree.tree('openNode', node2, slide, handleOpenNode);
1424 $tree.tree('openNode', node2, handleOpenNode);
1428 test('openNode with callback with slide true', function(assert) {
1429 test_open_node_with_callback(true, true, assert);
1432 test('openNode with callback with slide false', function(assert) {
1433 test_open_node_with_callback(false, true, assert);
1436 test('openNode with callback with slide null', function(assert) {
1437 test_open_node_with_callback(null, true, assert);
1440 test('openNode with callback without slide param', function(assert) {
1441 test_open_node_with_callback(null, false, assert);
1444 test('selectNode', function(assert) {
1446 var $tree = $('#tree1');
1452 var node1 = $tree.tree('getTree').children[0];
1453 var node2 = $tree.tree('getTree').children[1];
1454 var child3 = node2.children[0];
1456 assert.equal(child3.name, 'child3');
1457 assert.equal(node1.is_open, undefined);
1458 assert.equal(node2.is_open, undefined);
1459 assert.equal(child3.is_open, undefined);
1461 // -- select node 'child3', which is a child of 'node2'; must_open_parents = true
1462 $tree.tree('selectNode', child3, true);
1463 assert.equal($tree.tree('getSelectedNode').name, 'child3');
1465 assert.equal(node1.is_open, undefined);
1466 assert.equal(node2.is_open, true);
1467 assert.equal(child3.is_open, undefined);
1469 // -- select node 'node1'
1470 $tree.tree('selectNode', node1);
1471 assert.equal($tree.tree('getSelectedNode').name, 'node1');
1473 // -- is 'node1' selected?
1474 assert.equal($tree.tree('isNodeSelected', node1), true);
1477 $tree.tree('selectNode', null);
1478 assert.equal($tree.tree('getSelectedNode'), false);
1480 // -- is 'node1' selected?
1481 assert.equal($tree.tree('isNodeSelected', node1), false);
1484 test('selectNode when another node is selected', function(assert) {
1486 var $tree = $('#tree1');
1492 var node1 = $tree.tree('getTree').children[0];
1493 var node2 = $tree.tree('getTree').children[1];
1495 // -- select node 'node2'
1496 $tree.tree('selectNode', node2);
1497 assert.equal($tree.tree('getSelectedNode').name, 'node2');
1500 // -- is node 'node2' named 'deselected_node' in object's attributes?
1501 var is_select_event_fired = false;
1503 $tree.bind('tree.select', function(e) {
1504 assert.equal(e.deselected_node, node2);
1505 is_select_event_fired = true;
1508 // -- select node 'node1'; node 'node2' is selected before it
1509 $tree.tree('selectNode', node1);
1510 assert.equal($tree.tree('getSelectedNode').name, 'node1');
1512 assert.equal($tree.tree('isNodeSelected', node1), true);
1515 assert.ok(is_select_event_fired);
1518 test('click toggler', function(assert) {
1520 var done = assert.async();
1522 var $tree = $('#tree1');
1528 var $title = $tree.find('li:eq(0)').find('> .jqtree-element > span.jqtree-title');
1529 assert.equal($title.text(), 'node1');
1530 var $toggler = $title.prev();
1531 assert.ok($toggler.is('a.jqtree-toggler.jqtree-closed'));
1533 $tree.bind('tree.open', function(e) {
1534 // 2. handle 'open' event
1535 assert.equal(e.node.name, 'node1');
1537 // 3. click toggler again
1541 $tree.bind('tree.close', function(e) {
1542 assert.equal(e.node.name, 'node1');
1546 // 1. click toggler of 'node1'
1550 test('getNodeById', function(assert) {
1552 var $tree = $('#tree1');
1556 var node2 = $tree.tree('getNodeByName', 'node2');
1558 // 1. get 'node2' by id
1560 $tree.tree('getNodeById', 124).name,
1564 // 2. get id that does not exist
1565 assert.equal($tree.tree('getNodeById', 333), null);
1567 // 3. get id by string
1569 $tree.tree('getNodeById', '124').name,
1573 // 4. add node with string id; search by int
1583 $tree.tree('getNodeById', 234).name,
1587 $tree.tree('getNodeById', '234').name,
1591 // 5. load subtree in node2
1592 var subtree_data = [
1597 {label: 'sub2', id: 201}
1601 $tree.tree('loadData', subtree_data, node2);
1602 var t = $tree.tree('getTree');
1605 $tree.tree('getNodeById', 200).name,
1609 $tree.tree('getNodeById', 201).name,
1614 test('autoOpen', function(assert) {
1615 var $tree = $('#tree1');
1617 function formatOpenFolders() {
1618 var open_nodes = [];
1619 $tree.find('li').each(function() {
1621 if ($li.is('.jqtree-folder') && ! $li.is('.jqtree-closed')) {
1622 var label = $li.children('.jqtree-element').find('span').text();
1623 open_nodes.push(label);
1627 return open_nodes.join(';');
1659 // 1. autoOpen is false
1664 assert.equal(formatOpenFolders(), '');
1666 $tree.tree('destroy');
1668 // 2. autoOpen is true
1673 assert.equal(formatOpenFolders(), 'l1n1;l2n2;l3n1');
1675 $tree.tree('destroy');
1677 // 3. autoOpen level 1
1682 assert.equal(formatOpenFolders(), 'l1n1;l2n2');
1685 test('onCreateLi', function(assert) {
1686 // 1. init tree with onCreateLi
1687 var $tree = $('#tree1');
1690 onCreateLi: function(node, $li) {
1691 var $span = $li.children('.jqtree-element').find('span');
1692 $span.html('_' + node.name + '_');
1697 $tree.find('span:eq(0)').text(),
1702 test('save state', function(assert) {
1706 // Fake $.cookie plugin for browsers that do not support localstorage
1707 $.cookie = function(key, param2, param3) {
1708 if (typeof param3 == 'object') {
1718 // Remove state from localstorage
1719 if (typeof localStorage != 'undefined') {
1720 localStorage.setItem('my_tree', null);
1724 var $tree = $('#tree1');
1728 saveState: 'my_tree'
1731 var tree = $tree.tree('getTree');
1732 assert.equal($tree.tree('getSelectedNode'), false);
1734 // 2. select node -> state is saved
1735 $tree.tree('selectNode', tree.children[0]);
1736 assert.equal($tree.tree('getSelectedNode').name, 'node1');
1738 // 3. init tree again
1739 $tree.tree('destroy');
1744 saveState: 'my_tree'
1747 assert.equal($tree.tree('getSelectedNode').name, 'node1');
1752 test('generate hit areas', function(assert) {
1754 var $tree = $('#tree1');
1760 var node = $tree.tree('getNodeById', 123);
1761 var hit_areas = $tree.tree('testGenerateHitAreas', node);
1763 var strings = $.map(hit_areas, function(hit_area) {
1764 return hit_area.node.name + ' ' + Position.getName(hit_area.position);
1766 assert.equal(strings.join(';'), 'node1 none;node2 inside;node2 after');
1769 test('removeNode', function(assert) {
1771 var $tree = $('#tree1');
1777 // 1. Remove selected node; node is 'child1'
1778 var child1 = $tree.tree('getNodeByName', 'child1');
1779 $tree.tree('selectNode', child1);
1781 assert.equal($tree.tree('getSelectedNode').name, 'child1');
1783 $tree.tree('removeNode', child1);
1786 formatTitles($tree),
1787 'node1 child2 node2 child3'
1790 // getSelectedNode must now return false
1791 assert.equal($tree.tree('getSelectedNode'), false);
1793 // 2. No node is selected; remove child3
1794 $tree.tree('loadData', example_data);
1796 var child3 = $tree.tree('getNodeByName', 'child3');
1797 $tree.tree('removeNode', child3);
1800 formatTitles($tree),
1801 'node1 child1 child2 node2'
1804 assert.equal($tree.tree('getSelectedNode'), false);
1806 // 3. Remove parent of selected node
1807 $tree.tree('loadData', example_data);
1809 child1 = $tree.tree('getNodeByName', 'child1');
1810 var node1 = $tree.tree('getNodeByName', 'node1');
1812 $tree.tree('selectNode', child1);
1814 $tree.tree('removeNode', node1);
1816 // node is unselected
1817 assert.equal($tree.tree('getSelectedNode'), false);
1819 // 4. Remove unselected node without an id
1820 $tree.tree('loadData', example_data2);
1822 var c1 = $tree.tree('getNodeByName', 'c1');
1824 $tree.tree('removeNode', c1);
1827 formatTitles($tree),
1832 test('appendNode', function(assert) {
1834 var $tree = $('#tree1');
1839 var node1 = $tree.tree('getNodeByName', 'node1');
1841 // 1. Add child3 to node1
1842 $tree.tree('appendNode', 'child3', node1);
1845 formatTitles($(node1.element)),
1846 'node1 child1 child2 child3'
1849 // 2. Add child4 to child1
1850 var child1 = $tree.tree('getNodeByName', 'child1');
1852 // Node 'child1' does not have a toggler button
1854 $(child1.element).find('> .jqtree-element > .jqtree-toggler').length,
1858 $tree.tree('appendNode', 'child4', child1);
1860 assert.equal(formatTitles($(child1.element)), 'child1 child4');
1862 // Node 'child1' must get a toggler button
1864 $(child1.element).find('> .jqtree-element > .jqtree-toggler').length,
1869 test('prependNode', function(assert) {
1871 var $tree = $('#tree1');
1876 var node1 = $tree.tree('getNodeByName', 'node1');
1878 // 1. Prepend child0 to node1
1879 $tree.tree('prependNode', 'child0', node1);
1882 formatTitles($(node1.element)),
1883 'node1 child0 child1 child2'
1887 test('init event for local data', function(assert) {
1889 var done = assert.async();
1891 var $tree = $('#tree1');
1893 $tree.bind('tree.init', function() {
1894 // Check that we can call functions in 'tree.init' event
1895 assert.equal($tree.tree('getNodeByName', 'node2').name, 'node2');
1906 test('init event for ajax', function(assert) {
1908 var done = assert.async();
1910 var $tree = $('#tree1');
1914 responseText: example_data,
1918 $tree.bind('tree.init', function() {
1919 assert.equal($tree.tree('getNodeByName', 'node2').name, 'node2');
1930 test('updateNode', function(assert) {
1932 var $tree = $('#tree1');
1934 $tree.tree({ data: example_data });
1936 assert.equal(formatTitles($tree), 'node1 child1 child2 node2 child3');
1939 var node2 = $tree.tree('getNodeByName', 'node2');
1940 $tree.tree('updateNode', node2, 'CHANGED');
1942 assert.equal(formatTitles($tree), 'node1 child1 child2 CHANGED child3');
1943 assert.equal(node2.name, 'CHANGED');
1955 assert.equal(formatTitles($tree), 'node1 child1 child2 xyz child3');
1956 assert.equal(node2.name, 'xyz');
1957 assert.equal(node2.tag1, 'abc');
1960 assert.equal(node2.id, 124);
1962 $tree.tree('updateNode', node2, {id: 555});
1964 assert.equal(node2.id, 555);
1965 assert.equal(node2.name, 'xyz');
1968 var node_555 = $tree.tree('getNodeById', 555);
1969 assert.equal(node_555.name, 'xyz');
1971 var node_124 = $tree.tree('getNodeById', 124);
1972 assert.equal(node_124, undefined);
1975 var child1 = $tree.tree('getNodeByName', 'child1');
1977 $tree.tree('updateNode', child1, 'child1a');
1979 assert.equal(formatTitles($tree), 'node1 child1a child2 xyz child3');
1982 $tree.tree('selectNode', child1);
1983 $tree.tree('updateNode', child1, 'child1b');
1985 assert.ok($(child1.element).hasClass('jqtree-selected'));
1987 // add children to child1
1995 { id: 5, name: 'child1-1' }
2000 assert.equal(formatTitles($tree), 'node1 child1 child1-1 child2 xyz child3');
2013 assert.equal(formatTitles($tree), 'node1 child1 child2 xyz child3');
2016 test('moveNode', function(assert) {
2018 var $tree = $('#tree1');
2020 $tree.tree({ data: example_data });
2022 var child1 = $tree.tree('getNodeByName', 'child1');
2023 var child2 = $tree.tree('getNodeByName', 'child2');
2024 var node1 = $tree.tree('getNodeByName', 'node1');
2025 var node2 = $tree.tree('getNodeByName', 'node2');
2027 // -- Move child1 after node2
2028 $tree.tree('moveNode', child1, node2, 'after');
2030 assert.equal(formatTitles($tree), 'node1 child2 node2 child3 child1');
2032 // -- Check that illegal moves are skipped
2033 $tree.tree('moveNode', node1, child2, 'inside');
2036 test('load on demand', function(assert) {
2038 var done = assert.async();
2040 var $tree = $('#tree1');
2047 load_on_demand: true
2055 response: function(options) {
2056 assert.equal(options.url, '/tree/', '2');
2057 assert.deepEqual(options.data, { 'node' : 1 }, '3');
2059 this.responseText = [
2070 function handleOpenNode(node) {
2071 assert.equal(node.name, 'node1');
2072 assert.equal(formatTitles($tree), 'node1 child1', '4');
2077 var node1 = $tree.tree('getNodeByName', 'node1');
2078 assert.equal(formatTitles($tree), 'node1', '1');
2080 $tree.tree('openNode', node1, handleOpenNode);
2083 test('addNodeAfter', function(assert) {
2085 var $tree = $('#tree1');
2087 $tree.tree({ data: example_data });
2088 var node1 = $tree.tree('getNodeByName', 'node1');
2090 // -- add node after node1
2091 $tree.tree('addNodeAfter', 'node3', node1);
2093 assert.equal(formatTitles($tree), 'node1 child1 child2 node3 node2 child3');
2096 test('addNodeBefore', function(assert) {
2098 var $tree = $('#tree1');
2100 $tree.tree({ data: example_data });
2101 var node1 = $tree.tree('getNodeByName', 'node1');
2103 // -- add node before node1
2104 var new_node = $tree.tree('addNodeBefore', 'node3', node1);
2106 assert.equal(formatTitles($tree), 'node3 node1 child1 child2 node2 child3');
2109 test('addParentNode', function(assert) {
2111 var $tree = $('#tree1');
2113 $tree.tree({ data: example_data });
2114 var child3 = $tree.tree('getNodeByName', 'child3');
2116 // -- add parent to child3
2117 $tree.tree('addParentNode', 'node3', child3);
2119 assert.equal(formatTitles($tree), 'node1 child1 child2 node2 node3 child3');
2122 test('mouse events', function(assert) {
2124 var $tree = $('#tree1');
2130 $tree.tree('setMouseDelay', 0);
2132 function getTitleElement(node_name) {
2133 var node = $tree.tree('getNodeByName', node_name);
2134 var $el = $(node.element);
2135 return $($el.find('.jqtree-title'));
2138 var $node1 = getTitleElement('node1');
2139 var $child3 = getTitleElement('child3');
2141 // Move node1 inside child3
2142 // trigger mousedown event on node1
2144 $.Event('mousedown', { which: 1 })
2147 // trigger mouse move to child3
2148 var child3_offset = $child3.offset();
2150 $.Event('mousemove', { pageX: child3_offset.left, pageY: child3_offset.top })
2152 $tree.trigger('mouseup');
2155 formatTitles($tree),
2156 'node2 child3 node1 child1 child2'
2160 test('multiple select', function(assert) {
2162 var $tree = $('#tree1');
2163 $tree.tree({ data: example_data });
2165 var child1 = $tree.tree('getNodeByName', 'child1');
2166 var child2 = $tree.tree('getNodeByName', 'child2');
2168 // -- add nodes to selection
2169 // todo: more nodes as parameters?
2170 // todo: rename to 'selection.add' or 'selection' 'add'?
2171 $tree.tree('addToSelection', child1);
2172 $tree.tree('addToSelection', child2);
2174 // -- get selected nodes
2175 var selected_nodes = $tree.tree('getSelectedNodes');
2177 formatNodes(selected_nodes),
2182 test('keyboard', function(assert) {
2184 var $tree = $('#tree1');
2186 function keyDown(key) {
2188 $.Event('keydown', { which: key })
2192 $tree.tree({ data: example_data });
2194 var node1 = $tree.tree('getNodeByName', 'node1');
2197 $tree.tree('selectNode', node1);
2198 assert.equal(node1.is_open, undefined);
2200 // - move down; -> node2
2202 assert.equal($tree.tree('getSelectedNode').name, 'node2');
2204 // - move up; -> back to node1
2206 assert.equal($tree.tree('getSelectedNode').name, 'node1');
2208 // - move right; open node1
2210 assert.equal(node1.is_open, true);
2211 assert.equal($tree.tree('getSelectedNode').name, 'node1');
2213 // - select child3 and move up -> node2
2214 $tree.tree('selectNode', $tree.tree('getNodeByName', 'child3'));
2216 assert.equal($tree.tree('getSelectedNode').name, 'node2');
2218 // - move up -> child2
2220 assert.equal($tree.tree('getSelectedNode').name, 'child2');
2222 // - select node1 and move left -> close
2223 $tree.tree('selectNode', node1);
2225 assert.equal(node1.is_open, false);
2226 assert.equal($tree.tree('getSelectedNode').name, 'node1');
2229 test('getNodesByProperty', function(assert) {
2231 var $tree = $('#tree1');
2235 var node2 = $tree.tree('getNodeByName', 'node2');
2237 // 1. get 'node1' by property
2239 $tree.tree('getNodesByProperty', 'int_property', 1)[0].name,
2243 // 2. get property that does not exist in any node
2244 assert.equal($tree.tree('getNodesByProperty', 'int_property', 123).length, 0);
2246 // 3. get string property
2248 $tree.tree('getNodesByProperty', 'str_property', '1')[0].name,
2252 // 4. add node with string id; search by int
2258 str_property: '111',
2264 $tree.tree('getNodesByProperty', 'int_property', 111)[0].name,
2268 $tree.tree('getNodesByProperty', 'str_property', '111')[0].name,
2272 // 5. load subtree in node2
2273 var subtree_data = [
2279 {label: 'sub2', id: 201, int_property: 444}
2283 $tree.tree('loadData', subtree_data, node2);
2284 var t = $tree.tree('getTree');
2287 $tree.tree('getNodesByProperty', 'int_property', 222)[0].name,
2291 $tree.tree('getNodesByProperty', 'int_property', 444)[0].name,
2296 test('dataUrl extra options', function(assert) {
2297 var done = assert.async();
2299 var $tree = $('#tree1');
2303 response: function(options) {
2304 // 2. handle ajax request
2305 // expect 'headers' option
2306 assert.equal(options.url, '/tree2/');
2307 assert.deepEqual(options.headers, {'abc': 'def'});
2315 // dataUrl contains 'headers' option
2319 'headers': {'abc': 'def'}
2324 test('dataUrl is function', function(assert) {
2325 var done = assert.async();
2327 var $tree = $('#tree1');
2331 response: function(options) {
2332 // 2. handle ajax request
2333 // expect 'headers' option
2334 assert.equal(options.url, '/tree3/');
2335 assert.deepEqual(options.headers, {'abc': 'def'});
2343 // dataUrl is a function
2345 dataUrl: function(node) {
2348 'headers': {'abc': 'def'}
2354 test('getNodeByHtmlElement', function(assert) {
2355 var $tree = $('#tree1');
2360 var $el = $('.jqtree-title');
2362 // Get node for jquery element
2363 var node = $tree.tree('getNodeByHtmlElement', $el);
2364 assert.equal(node.name, 'node1');
2366 // Same for html element
2367 node = $tree.tree('getNodeByHtmlElement', $el[0]);
2368 assert.equal(node.name, 'node1');
2371 test('onLoadFailed', function(assert) {
2375 responseText: 'test error',
2379 var done = assert.async();
2381 function handleLoadFailed(e) {
2382 assert.equal(e.responseText, 'test error');
2387 var $tree = $('#tree1');
2390 onLoadFailed: handleLoadFailed
2394 },{"./utils_for_test":6,"jquery-mockjax":1}],4:[function(require,module,exports){
2395 var utils_for_test = require('./utils_for_test');
2397 var example_data = utils_for_test.example_data;
2398 var formatNodes = utils_for_test.formatNodes;
2400 var tree_vars = utils_for_test.getTreeVariables();
2402 var Node = tree_vars.Node;
2403 var Position = tree_vars.Position;
2405 var test = QUnit.test;
2408 QUnit.module("Tree");
2409 test('constructor', function(assert) {
2410 // 1. Create node from string
2411 var node = new Node('n1');
2413 assert.equal(node.name, 'n1');
2414 assert.equal(node.children.length, 0);
2415 assert.equal(node.parent, null);
2417 // 2. Create node from object
2421 parent: 'abc', // parent must be ignored
2422 children: ['c'], // children must be ignored
2426 assert.equal(node.name, 'n2');
2427 assert.equal(node.id, 123);
2428 assert.equal(node.url, '/');
2429 assert.equal(node.label, undefined);
2430 assert.equal(node.children.length, 0);
2431 assert.equal(node.parent, null);
2434 test("create tree from data", function(assert) {
2435 function checkData(tree) {
2437 formatNodes(tree.children),
2442 formatNodes(tree.children[0].children),
2447 formatNodes(tree.children[1].children),
2452 tree.children[0].id,
2458 // - create tree from example data
2459 var tree = new Node(null, true);
2460 tree.loadFromData(example_data);
2463 // - create tree from new data format
2468 children: ['child1', 'child2'] // nodes are only defined by a string
2473 children: ['child3']
2476 var tree = new Node(null, true);
2477 tree.loadFromData(data);
2481 test("addChild", function(assert) {
2482 var tree = new Node('tree1', true);
2491 formatNodes(tree.children),
2496 var node = tree.children[0];
2504 test('addChildAtPosition', function(assert) {
2505 var tree = new Node(null, true);
2506 tree.addChildAtPosition(new Node('abc'), 0); // first
2507 tree.addChildAtPosition(new Node('ghi'), 2); // index 2 does not exist
2508 tree.addChildAtPosition(new Node('def'), 1);
2509 tree.addChildAtPosition(new Node('123'), 0);
2512 formatNodes(tree.children),
2518 test('removeChild', function(assert) {
2519 var tree = new Node(null, true);
2521 var abc = new Node({'label': 'abc', 'id': 1});
2522 var def = new Node({'label': 'def', 'id': 2});
2523 var ghi = new Node({'label': 'ghi', 'id': 3});
2529 var jkl = new Node({'label': 'jkl', 'id': 4});
2533 formatNodes(tree.children),
2538 assert.equal(tree.id_mapping[2].name, 'def');
2539 assert.equal(tree.id_mapping[4].name, 'jkl');
2542 tree.removeChild(def);
2544 formatNodes(tree.children),
2549 assert.equal(tree.id_mapping[2], null);
2550 assert.equal(tree.id_mapping[4], null);
2553 tree.removeChild(ghi);
2555 formatNodes(tree.children),
2561 tree.removeChild(abc);
2563 formatNodes(tree.children),
2569 test('getChildIndex', function(assert) {
2571 var tree = new Node(null, true);
2573 var abc = new Node('abc');
2574 var def = new Node('def');
2575 var ghi = new Node('ghi');
2580 // 1. Get child index of 'def'
2581 assert.equal(tree.getChildIndex(def), 1);
2583 // 2. Get child index of non-existing node
2584 assert.equal(tree.getChildIndex(new Node('xyz')), -1);
2587 test('hasChildren', function(assert) {
2588 var tree = new Node(null, true);
2592 'tree without children'
2595 tree.addChild(new Node('abc'));
2603 test('iterate', function(assert) {
2604 var tree = new Node(null, true);
2605 tree.loadFromData(example_data);
2607 // iterate over all the nodes
2610 function(node, level) {
2618 'node1 child1 child2 node2 child3',
2622 // iterate over nodes on first level
2625 function(node, level) {
2634 'nodes on first level'
2638 var node3 = tree.getNodeById(124).children[0];
2643 // test level parameter
2646 function(node, level) {
2647 nodes.push(node.name + ' ' + level);
2654 'node1 0,child1 1,child2 1,node2 0,child3 1,child4 2'
2658 test('moveNode', function(assert) {
2659 var tree = new Node(null, true);
2660 tree.loadFromData(example_data);
2670 var node1 = tree.children[0];
2671 var node2 = tree.children[1];
2672 var child1 = node1.children[0];
2673 var child2 = node1.children[1];
2674 assert.equal(node2.name, 'node2', 'node2 name');
2675 assert.equal(child2.name, 'child2', 'child2 name');
2677 // move child2 after node2
2678 tree.moveNode(child2, node2, Position.AFTER);
2688 formatNodes(tree.children),
2689 'node1 node2 child2',
2690 'tree nodes at first level'
2693 formatNodes(node1.children),
2698 // move child1 inside node2
2699 // this means it's the first child
2700 tree.moveNode(child1, node2, Position.INSIDE);
2710 formatNodes(node2.children),
2715 formatNodes(node1.children),
2717 'node1 has no children'
2720 // move child2 before child1
2721 tree.moveNode(child2, child1, Position.BEFORE);
2731 formatNodes(node2.children),
2732 'child2 child1 child3',
2736 formatNodes(tree.children),
2738 'tree nodes at first level'
2742 test('initFromData', function(assert) {
2754 var node = new Node(null, true);
2755 node.initFromData(data);
2757 assert.equal(node.name, 'main')
2759 formatNodes(node.children),
2763 assert.equal(node.children[1].id, 201);
2766 test('getData', function(assert) {
2768 var node = new Node(null, true);
2769 assert.deepEqual(node.getData(), []);
2798 // 3. get data including parent
2799 var n1 = node.getNodeByName('n1');
2814 test('addAfter', function(assert) {
2816 var tree = new Node(null, true);
2817 tree.loadFromData(example_data);
2827 assert.equal(formatNodes(tree.children), 'node1 node2');
2829 // - Add 'node_b' after node2
2830 var node2 = tree.getNodeByName('node2');
2831 node2.addAfter('node_b');
2833 assert.equal(formatNodes(tree.children), 'node1 node2 node_b');
2835 var node_b = tree.getNodeByName('node_b');
2836 assert.equal(node_b.name, 'node_b');
2838 // - Add 'node_a' after node1
2839 var node1 = tree.getNodeByName('node1');
2840 node1.addAfter('node_a');
2842 assert.equal(formatNodes(tree.children), 'node1 node_a node2 node_b');
2844 // - Add 'node_c' after node_b; new node is an object
2850 var node_c = tree.getNodeByName('node_c');
2851 assert.equal(node_c.id, 789);
2853 assert.equal(formatNodes(tree.children), 'node1 node_a node2 node_b node_c');
2855 // - Add after root node; this is not possible
2856 assert.equal(tree.addAfter('node_x'), null);
2859 test('addBefore', function(assert) {
2861 var tree = new Node(null, true);
2862 tree.loadFromData(example_data);
2864 // - Add 'node_0' before node1
2865 var node1 = tree.getNodeByName('node1');
2866 node1.addBefore('node0');
2867 assert.equal(formatNodes(tree.children), 'node0 node1 node2');
2869 // - Add before root node; this is not possile
2870 assert.equal(tree.addBefore('x'), null);
2873 test('addParent', function(assert) {
2875 var tree = new Node(null, true);
2876 tree.loadFromData(example_data);
2878 // - Add node 'root' as parent of node1
2879 // Note that node also becomes a child of 'root'
2880 var node1 = tree.getNodeByName('node1');
2881 node1.addParent('root');
2883 var root = tree.getNodeByName('root');
2884 assert.equal(formatNodes(root.children), 'node1 node2');
2886 // - Add parent to root node; not possible
2887 assert.equal(tree.addParent('x'), null);
2890 test('remove', function(assert) {
2892 var tree = new Node(null, true);
2893 tree.loadFromData(example_data);
2895 var child1 = tree.getNodeByName('child1');
2896 var node1 = tree.getNodeByName('node1');
2898 assert.equal(formatNodes(node1.children), 'child1 child2');
2899 assert.equal(child1.parent, node1);
2904 assert.equal(formatNodes(node1.children), 'child2');
2905 assert.equal(child1.parent, null);
2908 test('append', function(assert) {
2910 var tree = new Node(null, true);
2911 tree.loadFromData(example_data);
2913 var node1 = tree.getNodeByName('node1');
2915 // 1. Append child3 to node1
2916 node1.append('child3');
2918 assert.equal(formatNodes(node1.children), 'child1 child2 child3');
2920 // 2. Append subtree
2930 assert.equal(formatNodes(node1.children), 'child1 child2 child3 child4');
2932 var child4 = node1.getNodeByName('child4');
2933 assert.equal(formatNodes(child4.children), 'child5');
2936 test('prepend', function(assert) {
2938 var tree = new Node(null, true);
2939 tree.loadFromData(example_data);
2941 var node1 = tree.getNodeByName('node1');
2943 // 1. Prepend child0 to node1
2944 node1.prepend('child0');
2946 assert.equal(formatNodes(node1.children), 'child0 child1 child2');
2948 // 2. Prepend subtree
2956 assert.equal(formatNodes(node1.children), 'child3 child0 child1 child2');
2958 var child3 = node1.getNodeByName('child3');
2959 assert.equal(formatNodes(child3.children), 'child4');
2962 test('getNodeById', function(assert) {
2964 var tree = new Node(null, true);
2965 tree.loadFromData(example_data);
2967 // 1. Get node with id 124
2968 var node = tree.getNodeById(124);
2969 assert.equal(node.name, 'node2');
2971 // 2. Delete node with id 124 and search again
2974 assert.equal(tree.getNodeById(124), null);
2976 // 3. Add node with id 456 and search for it
2977 var child3 = tree.getNodeByName('child2');
2983 node = tree.getNodeById(456);
2984 assert.equal(node.name, 'new node');
2987 test('getLevel', function(assert) {
2989 var tree = new Node(null, true);
2990 tree.loadFromData(example_data);
2992 // 1. get level for node1 and child1
2993 assert.equal(tree.getNodeByName('node1').getLevel(), 1);
2994 assert.equal(tree.getNodeByName('child1').getLevel(), 2);
2997 test('loadFromData and id mapping', function(assert) {
2998 // - get node from empty tree
2999 var tree = new Node(null, true);
3000 assert.equal(tree.getNodeById(999), null);
3002 // - load example data in tree
3003 tree.loadFromData(example_data);
3004 assert.equal(tree.getNodeById(124).name, 'node2');
3006 var child2 = tree.getNodeById(126);
3008 new Node({label: 'child4', id: 128})
3011 new Node({label: 'child5', id: 129})
3014 // - load data in node child2
3015 child2.loadFromData(['abc', 'def']);
3017 assert.equal(tree.getNodeById(128), null);
3018 assert.equal(child2.children.length, 2);
3019 assert.equal(child2.children[0].name, 'abc');
3022 test('removeChildren', function(assert) {
3023 // - load example data
3024 var tree = new Node(null, true);
3025 tree.loadFromData(example_data);
3027 // add child4 and child5
3028 var child2 = tree.getNodeById(126);
3029 assert.equal(child2.name, 'child2');
3032 new Node({label: 'child4', id: 128})
3035 new Node({label: 'child5', id: 129})
3037 assert.equal(tree.getNodeById(128).name, 'child4');
3039 // - remove children from child2
3040 child2.removeChildren();
3041 assert.equal(tree.getNodeById(128), null);
3042 assert.equal(child2.children.length, 0);
3045 test('node with id 0', function(assert) {
3046 // - load node with id 0
3047 var tree = new Node(null, true);
3056 var node = tree.getNodeById(0);
3057 assert.equal(node.name, 'mynode');
3059 // -- remove the node
3062 assert.equal(tree.getNodeById(0), undefined);
3065 test('getPreviousSibling', function(assert) {
3067 var tree = new Node(null, true);
3068 tree.loadFromData(example_data);
3070 // - getPreviousSibling
3072 tree.getNodeByName('child2').getPreviousSibling().name,
3075 assert.equal(tree.getPreviousSibling(), null);
3077 tree.getNodeByName('child1').getPreviousSibling(),
3082 test('getNextSibling', function(assert) {
3084 var tree = new Node(null, true);
3085 tree.loadFromData(example_data);
3089 tree.getNodeByName('node1').getNextSibling().name,
3093 tree.getNodeByName('node2').getNextSibling(),
3096 assert.equal(tree.getNextSibling(), null);
3099 test('getNodesByProperty', function(assert) {
3100 var tree = new Node(null, true);
3101 tree.loadFromData(example_data);
3103 nodes = tree.getNodesByProperty('name', 'child1');
3105 assert.equal(nodes.length, 1);
3106 assert.equal(nodes[0].name, 'child1');
3109 test('getNodeByCallback', function(assert) {
3110 var tree = new Node(null, true);
3111 tree.loadFromData(example_data);
3113 node = tree.getNodeByCallback(
3115 return node.name == 'child1';
3119 assert.equal(node.name, 'child1');
3122 },{"./utils_for_test":6}],5:[function(require,module,exports){
3123 var utils_for_test = require('./utils_for_test');
3125 var tree_vars = utils_for_test.getTreeVariables();
3127 var Position = tree_vars.Position;
3128 var util = tree_vars.util;
3130 var test = QUnit.test;
3133 QUnit.module('util');
3135 test('indexOf', function(assert) {
3136 var _indexOf = util._indexOf;
3137 var indexOf = util.indexOf;
3139 assert.equal(indexOf([3, 2, 1], 1), 2);
3140 assert.equal(_indexOf([3, 2, 1], 1), 2);
3141 assert.equal(indexOf([4, 5, 6], 1), -1);
3142 assert.equal(_indexOf([4, 5, 6], 1), -1);
3145 test('Position.getName', function(assert) {
3146 assert.equal(Position.getName(Position.BEFORE), 'before');
3147 assert.equal(Position.getName(Position.AFTER), 'after');
3148 assert.equal(Position.getName(Position.INSIDE), 'inside');
3149 assert.equal(Position.getName(Position.NONE), 'none');
3152 test('Position.nameToIndex', function(assert) {
3153 assert.equal(Position.nameToIndex('before'), Position.BEFORE);
3154 assert.equal(Position.nameToIndex('after'), Position.AFTER);
3155 assert.equal(Position.nameToIndex(''), 0);
3158 },{"./utils_for_test":6}],6:[function(require,module,exports){
3169 var example_data = [
3172 id: 123, // extra data
3176 { label: 'child1', id: 125, int_property: 2 },
3177 { label: 'child2', id: 126 }
3186 { label: 'child3', id: 127 }
3199 var example_data2 = [
3209 function formatNodes(nodes) {
3210 var strings = $.map(nodes, function(node) {
3213 return strings.join(' ');
3216 function isNodeClosed($node) {
3218 ($node.is('li.jqtree-folder.jqtree-closed')) &&
3219 ($node.find('a:eq(0)').is('a.jqtree-toggler.jqtree-closed')) &&
3220 ($node.find('ul:eq(0)').is('ul'))
3224 function isNodeOpen($node) {
3226 ($node.is('li.jqtree-folder')) &&
3227 ($node.find('a:eq(0)').is('a.jqtree-toggler')) &&
3228 ($node.find('ul:eq(0)').is('ul')) &&
3229 (! $node.is('li.jqtree-folder.jqtree-closed')) &&
3230 (! $node.find('span:eq(0)').is('a.jqtree-toggler.jqtree-closed'))
3234 function formatTitles($node) {
3235 var titles = $node.find('.jqtree-title').map(
3237 return $(el).text();
3240 return titles.toArray().join(' ');
3243 function getTreeVariables() {
3244 var JqTreeWidget = $('').tree('get_widget_class');
3246 var node = JqTreeWidget.getModule('node');
3247 var util = JqTreeWidget.getModule('util');
3251 Position: node.Position,
3258 example_data: example_data,
3259 example_data2: example_data2,
3260 formatNodes: formatNodes,
3261 formatTitles: formatTitles,
3262 getTreeVariables: getTreeVariables,
3263 isNodeClosed: isNodeClosed,
3264 isNodeOpen: isNodeOpen