PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
← All changes | assets/src/js/admin/course-material.js +301 -301 4.3.84.4.8 View file →
@@ -1,301 +1,301 @@
1 -document.addEventListener( 'DOMContentLoaded', function() {
2 - const $ = window.jQuery;
3 - const postID = document.getElementById( 'current-material-post-id' ).value,
4 - max_file_size = document.getElementById( 'material-max-file-size' ).value,
5 - accept_file = document.querySelector( '.lp-material--field-upload' ).getAttribute( 'accept' ).split( ',' ),
6 - can_upload = document.getElementById( 'available-to-upload' ),
7 - add_btn = document.getElementById( 'btn-lp--add-material' ),
8 - group_template = document.getElementById( 'lp-material--add-material-template' ),
9 - material__group_container = document.getElementById( 'lp-material--group-container' ),
10 - material_tab = document.getElementById( 'lp-material-container' ),
11 - material_save_btn = document.getElementById( 'btn-lp--save-material' );
12 - const getResponse = async ( ele, postID ) => {
13 - const elementMaterial = document.querySelector( '.lp-material--table tbody' );
14 - try {
15 - const url = `${ lpDataAdmin.lp_rest_url }lp/v1/material/item-materials/${ postID }`;
16 - fetch( url, {
17 - method: 'GET',
18 - headers: {
19 - 'X-WP-Nonce': lpGlobalSettings.nonce,
20 - 'Content-Type': 'application/json',
21 - },
22 - } )
23 - .then( ( response ) => response.json() )
24 - .then( ( response ) => {
25 - const { data, status } = response;
26 - if ( status !== 'success' ) {
27 - console.error( response.message );
28 - return;
29 - }
30 -
31 - if ( data && data.items && data.items.length > 0 ) {
32 - const materials = data.items;
33 - if ( ele.querySelector( '.lp-skeleton-animation' ) ) {
34 - ele.querySelector( '.lp-skeleton-animation' ).remove();
35 - }
36 - for ( let i = 0; i < materials.length; i++ ) {
37 - insertRow( elementMaterial, materials[ i ] );
38 - }
39 - }
40 - } )
41 - .catch( ( err ) => console.log( err ) );
42 - } catch ( error ) {
43 - console.log( error.message );
44 - }
45 - };
46 - const insertRow = ( parent, data ) => {
47 - if ( ! parent ) {
48 - return;
49 - }
50 - const delete_btn_text = document.getElementById( 'delete-material-row-text' ).value;
51 - parent.insertAdjacentHTML(
52 - 'beforeend',
53 - `<tr data-id="${ data.file_id }" data-sort="${ data.orders }" >
54 - <td class="sort"><span class="dashicons dashicons-menu"></span> ${ data.file_name }</td>
55 - <td>${ capitalizeFirstChar( data.method ) }</td>
56 - <td><a href="javascript:void(0)" class="delete-material-row" data-id="${ data.file_id }">${ delete_btn_text }</a></td>
57 - </tr>`
58 - );
59 - };
60 - const capitalizeFirstChar = ( str ) => str.charAt( 0 ).toUpperCase() + str.substring( 1 );
61 - //load material data from API
62 - getResponse( material_tab, postID );
63 -
64 - //add material group field
65 - add_btn.addEventListener( 'click', function( e ) {
66 - const can_upload_data = ~~this.getAttribute( 'can-upload' );
67 - const groups = material__group_container.querySelectorAll( '.lp-material--group' ).length;
68 - if ( groups >= can_upload_data ) {
69 - return false;
70 - }
71 - material__group_container.insertAdjacentHTML( 'afterbegin', group_template.innerHTML );
72 - } );
73 - //switch input when change method between "upload" and "external"
74 - material_tab.addEventListener( 'change', function( event ) {
75 - const target = event.target;
76 - if ( target.classList.contains( 'lp-material--field-method' ) ) {
77 - const method = target.value;
78 - const upload_field_template = document.getElementById( 'lp-material--upload-field-template' ).innerHTML,
79 - external_field_template = document.getElementById( 'lp-material--external-field-template' ).innerHTML;
80 - switch ( method ) {
81 - case 'upload' :
82 - target.parentNode.insertAdjacentHTML( 'afterend', upload_field_template );
83 - target.closest( '.lp-material--group' ).querySelector( '.lp-material--external-wrap' ).remove();
84 - break;
85 - case 'external' :
86 - target.parentNode.insertAdjacentHTML( 'afterend', external_field_template );
87 - target.closest( '.lp-material--group' ).querySelector( '.lp-material--upload-wrap' ).remove();
88 - break;
89 - }
90 - }
91 - if ( target.classList.contains( 'lp-material--field-upload' ) ) {
92 - if ( target.value && target.files.length > 0 ) {
93 - if ( ! accept_file.includes( target.files[ 0 ].type ) ) {
94 - alert( 'This file is not allowed! Please choose another file!' );
95 - target.value = '';
96 - } else if ( target.files[ 0 ].size > max_file_size * 1024 * 1024 ) {
97 - alert( `This file size is greater than ${ max_file_size }MB! Please choose another file!` );
98 - target.value = '';
99 - }
100 - }
101 - }
102 - } );
103 - // Dynamic click action ...
104 - material_tab.addEventListener( 'click', function( event ) {
105 - const target = event.target;
106 - if ( target.classList.contains( 'lp-material--delete' ) && target.nodeName == 'BUTTON' ) {
107 - target.closest( '.lp-material--group' ).remove();
108 - } else if ( target.classList.contains( 'lp-material-save-field' ) ) {
109 - // save a file
110 - let material = target.closest( '.lp-material--group' );
111 - material = singleNode( material );
112 - // target.classList.add( 'loading' );
113 - lpSaveMaterial( material, true, target );
114 - // target.classList.remove( 'loading' );
115 - }
116 - return false;
117 - } );
118 -
119 - //save all material files
120 - material_save_btn.addEventListener( 'click', function( event ) {
121 - const materials = material__group_container.querySelectorAll( '.lp-material--group' );
122 - if ( materials.length > 0 ) {
123 - // material_save_btn.classList.add( 'loading' );
124 - lpSaveMaterial( materials, false, material_save_btn );
125 - // material_save_btn.classList.remove( 'loading' );
126 - }
127 - } );
128 - function lpSaveMaterial( materials, is_single = false, target ) {
129 - if ( materials.length > 0 ) {
130 - let material_data = [];
131 - let formData = new FormData(),
132 - send_request = true;
133 -
134 - materials.forEach( function( ele, index ) {
135 - const label = ele.querySelector( '.lp-material--field-title' ).value,
136 - method = ele.querySelector( '.lp-material--field-method' ).value,
137 - external_field = ele.querySelector( '.lp-material--field-external-link' ),
138 - upload_field = ele.querySelector( '.lp-material--field-upload' );
139 - let file, link;
140 - if ( ! label ) {
141 - send_request = false;
142 - }
143 - switch ( method ) {
144 - case 'upload' :
145 - if ( upload_field.value ) {
146 - file = upload_field.files[ 0 ].name;
147 - link = '';
148 - formData.append( 'file[]', upload_field.files[ 0 ] );
149 - } else {
150 - send_request = false;
151 - }
152 - break;
153 - case 'external' :
154 - link = external_field.value;
155 - file = '';
156 - if ( ! link ) {
157 - send_request = false;
158 - }
159 - break;
160 - }
161 - material_data.push( { label, method, file, link } );
162 - } );
163 -
164 - if ( ! send_request ) {
165 - alert( 'Enter file title, choose file or enter file link!' );
166 - } else {
167 - // console.log(material_data);
168 - material_data = JSON.stringify( material_data );
169 - const url = `${ lpGlobalSettings.rest }lp/v1/material/item-materials/${ postID }`;
170 - formData.append( 'data', material_data );
171 - target.classList.add( 'loading' );
172 -
173 - fetch( url, {
174 - method: 'POST',
175 - headers: {
176 - 'X-WP-Nonce': lpGlobalSettings.nonce,
177 - },
178 - body: formData,
179 - } ) // wrapped
180 - .then( ( res ) => res.text() )
181 - .then( ( resString ) => {
182 - // console.log( data );
183 - if ( ! is_single ) {
184 - material__group_container.innerHTML = '';
185 - } else {
186 - materials[ 0 ].remove();
187 - }
188 - const res = JSON.parse( resString );
189 - const { message, data, status } = res;
190 - alert( message );
191 -
192 - if ( status === 'success' ) {
193 - if ( data.length > 0 ) {
194 - const material_table = document.querySelector( '.lp-material--table' );
195 - const thead = material_table.querySelector( 'thead' );
196 - const tbody = material_table.querySelector( 'tbody' );
197 -
198 - thead.classList.remove( 'hidden' );
199 - for ( let i = 0; i < data.length; i++ ) {
200 - const row = data[ i ];
201 - insertRow( tbody, row );
202 - }
203 - can_upload.innerText = parseInt( can_upload.innerText ) - data.length;
204 - add_btn.setAttribute( 'can-upload', can_upload.innerText );
205 - }
206 - }
207 - } )
208 - .finally( () => {
209 - target.classList.remove( 'loading' );
210 - } )
211 - .catch( ( err ) => console.log( err ) );
212 - }
213 - }
214 - }
215 - //delete material
216 - document.addEventListener( 'click', function( e ) {
217 - const target = e.target;
218 - if ( target.classList.contains( 'delete-material-row' ) && target.nodeName == 'A' ) {
219 - const rowID = target.getAttribute( 'data-id' ), //material file ID
220 - message = document.getElementById( 'delete-material-message' ).value;//Delete message content
221 - if ( confirm( message ) ) {
222 - wp.apiFetch( {
223 - path: `lp/v1/material/${ rowID }`,
224 - method: 'DELETE',
225 - data: {
226 - item_id: postID,
227 - },
228 - } ).then( ( res ) => {
229 - // console.log( res );
230 - if ( res.status !== 200 || ! res.delete ) {
231 - alert( res.message );
232 - } else {
233 - target.closest( 'tr' ).remove();
234 - can_upload.innerText = ~~can_upload.innerText + 1;
235 - add_btn.setAttribute( 'can-upload', ~~can_upload.innerText );
236 - }
237 - } ).catch( ( err ) => {
238 - console.log( err );
239 - } ).finally( () => {
240 -
241 - } );
242 - }
243 - }
244 - } );
245 - const singleNode = ( ( nodeList ) => ( node ) => {
246 - const layer = { // define our specific case
247 - 0: { value: node, enumerable: true },
248 - length: { value: 1 },
249 - item: {
250 - value( i ) {
251 - return this[ +i || 0 ];
252 - },
253 - enumerable: true,
254 - },
255 - };
256 - return Object.create( nodeList, layer ); // put our case on top of true NodeList
257 - } )( document.createDocumentFragment().childNodes ); // scope a true NodeList
258 - $( '.lp-material--table tbody' ).sortable( {
259 - items: 'tr',
260 - cursor: 'move',
261 - axis: 'y',
262 - handle: 'td.sort',
263 - scrollSensitivity: 40,
264 - forcePlaceholderSize: true,
265 - helper: 'clone',
266 - opacity: 0.65,
267 - update( event, ui ) {
268 - $( this ).sortable( 'option', 'disabled', true );
269 - updateSort();
270 - $( this ).sortable( 'option', 'disabled', false );
271 - },
272 - } );
273 - function updateSort() {
274 - const items = $( '.lp-material--table tbody tr' ),
275 - data = [];
276 - // $( ".lp-material--table tbody tr" ).sortable( "option", "disabled", true );
277 - items.each( function( i, item ) {
278 - $( this ).attr( 'data-sort', i + 1 );
279 - data.push( { file_id: ~~$( this ).attr( 'data-id' ), orders: i + 1 } );
280 - } );
281 - wp.apiFetch( {
282 - path: `lp/v1/material/item-materials/${ postID }`,
283 - method: 'PUT',
284 - data: {
285 - sort_arr: JSON.stringify( data ),
286 - },
287 - } ).then( ( res ) => {
288 - if ( res.status == 200 ) {
289 - //
290 - } else {
291 - alert( 'Sort table fail.' );
292 - }
293 - } ).catch( ( err ) => {
294 - console.log( err );
295 - } ).finally( () => {
296 -
297 - } );
298 - // $( ".lp-material--table tbody tr" ).sortable( "option", "disabled", false );
299 - // console.log( data );
300 - }
301 -} );
1 +document.addEventListener( 'DOMContentLoaded', function() {
2 + const $ = window.jQuery;
3 + const postID = document.getElementById( 'current-material-post-id' ).value,
4 + max_file_size = document.getElementById( 'material-max-file-size' ).value,
5 + accept_file = document.querySelector( '.lp-material--field-upload' ).getAttribute( 'accept' ).split( ',' ),
6 + can_upload = document.getElementById( 'available-to-upload' ),
7 + add_btn = document.getElementById( 'btn-lp--add-material' ),
8 + group_template = document.getElementById( 'lp-material--add-material-template' ),
9 + material__group_container = document.getElementById( 'lp-material--group-container' ),
10 + material_tab = document.getElementById( 'lp-material-container' ),
11 + material_save_btn = document.getElementById( 'btn-lp--save-material' );
12 + const getResponse = async ( ele, postID ) => {
13 + const elementMaterial = document.querySelector( '.lp-material--table tbody' );
14 + try {
15 + const url = `${ lpDataAdmin.lp_rest_url }lp/v1/material/item-materials/${ postID }`;
16 + fetch( url, {
17 + method: 'GET',
18 + headers: {
19 + 'X-WP-Nonce': lpGlobalSettings.nonce,
20 + 'Content-Type': 'application/json',
21 + },
22 + } )
23 + .then( ( response ) => response.json() )
24 + .then( ( response ) => {
25 + const { data, status } = response;
26 + if ( status !== 'success' ) {
27 + console.error( response.message );
28 + return;
29 + }
30 +
31 + if ( data && data.items && data.items.length > 0 ) {
32 + const materials = data.items;
33 + if ( ele.querySelector( '.lp-skeleton-animation' ) ) {
34 + ele.querySelector( '.lp-skeleton-animation' ).remove();
35 + }
36 + for ( let i = 0; i < materials.length; i++ ) {
37 + insertRow( elementMaterial, materials[ i ] );
38 + }
39 + }
40 + } )
41 + .catch( ( err ) => console.log( err ) );
42 + } catch ( error ) {
43 + console.log( error.message );
44 + }
45 + };
46 + const insertRow = ( parent, data ) => {
47 + if ( ! parent ) {
48 + return;
49 + }
50 + const delete_btn_text = document.getElementById( 'delete-material-row-text' ).value;
51 + parent.insertAdjacentHTML(
52 + 'beforeend',
53 + `<tr data-id="${ data.file_id }" data-sort="${ data.orders }" >
54 + <td class="sort"><span class="dashicons dashicons-menu"></span> ${ data.file_name }</td>
55 + <td>${ capitalizeFirstChar( data.method ) }</td>
56 + <td><a href="javascript:void(0)" class="delete-material-row" data-id="${ data.file_id }">${ delete_btn_text }</a></td>
57 + </tr>`
58 + );
59 + };
60 + const capitalizeFirstChar = ( str ) => str.charAt( 0 ).toUpperCase() + str.substring( 1 );
61 + //load material data from API
62 + getResponse( material_tab, postID );
63 +
64 + //add material group field
65 + add_btn.addEventListener( 'click', function( e ) {
66 + const can_upload_data = ~~this.getAttribute( 'can-upload' );
67 + const groups = material__group_container.querySelectorAll( '.lp-material--group' ).length;
68 + if ( groups >= can_upload_data ) {
69 + return false;
70 + }
71 + material__group_container.insertAdjacentHTML( 'afterbegin', group_template.innerHTML );
72 + } );
73 + //switch input when change method between "upload" and "external"
74 + material_tab.addEventListener( 'change', function( event ) {
75 + const target = event.target;
76 + if ( target.classList.contains( 'lp-material--field-method' ) ) {
77 + const method = target.value;
78 + const upload_field_template = document.getElementById( 'lp-material--upload-field-template' ).innerHTML,
79 + external_field_template = document.getElementById( 'lp-material--external-field-template' ).innerHTML;
80 + switch ( method ) {
81 + case 'upload' :
82 + target.parentNode.insertAdjacentHTML( 'afterend', upload_field_template );
83 + target.closest( '.lp-material--group' ).querySelector( '.lp-material--external-wrap' ).remove();
84 + break;
85 + case 'external' :
86 + target.parentNode.insertAdjacentHTML( 'afterend', external_field_template );
87 + target.closest( '.lp-material--group' ).querySelector( '.lp-material--upload-wrap' ).remove();
88 + break;
89 + }
90 + }
91 + if ( target.classList.contains( 'lp-material--field-upload' ) ) {
92 + if ( target.value && target.files.length > 0 ) {
93 + if ( ! accept_file.includes( target.files[ 0 ].type ) ) {
94 + alert( 'This file is not allowed! Please choose another file!' );
95 + target.value = '';
96 + } else if ( target.files[ 0 ].size > max_file_size * 1024 * 1024 ) {
97 + alert( `This file size is greater than ${ max_file_size }MB! Please choose another file!` );
98 + target.value = '';
99 + }
100 + }
101 + }
102 + } );
103 + // Dynamic click action ...
104 + material_tab.addEventListener( 'click', function( event ) {
105 + const target = event.target;
106 + if ( target.classList.contains( 'lp-material--delete' ) && target.nodeName == 'BUTTON' ) {
107 + target.closest( '.lp-material--group' ).remove();
108 + } else if ( target.classList.contains( 'lp-material-save-field' ) ) {
109 + // save a file
110 + let material = target.closest( '.lp-material--group' );
111 + material = singleNode( material );
112 + // target.classList.add( 'loading' );
113 + lpSaveMaterial( material, true, target );
114 + // target.classList.remove( 'loading' );
115 + }
116 + return false;
117 + } );
118 +
119 + //save all material files
120 + material_save_btn.addEventListener( 'click', function( event ) {
121 + const materials = material__group_container.querySelectorAll( '.lp-material--group' );
122 + if ( materials.length > 0 ) {
123 + // material_save_btn.classList.add( 'loading' );
124 + lpSaveMaterial( materials, false, material_save_btn );
125 + // material_save_btn.classList.remove( 'loading' );
126 + }
127 + } );
128 + function lpSaveMaterial( materials, is_single = false, target ) {
129 + if ( materials.length > 0 ) {
130 + let material_data = [];
131 + let formData = new FormData(),
132 + send_request = true;
133 +
134 + materials.forEach( function( ele, index ) {
135 + const label = ele.querySelector( '.lp-material--field-title' ).value,
136 + method = ele.querySelector( '.lp-material--field-method' ).value,
137 + external_field = ele.querySelector( '.lp-material--field-external-link' ),
138 + upload_field = ele.querySelector( '.lp-material--field-upload' );
139 + let file, link;
140 + if ( ! label ) {
141 + send_request = false;
142 + }
143 + switch ( method ) {
144 + case 'upload' :
145 + if ( upload_field.value ) {
146 + file = upload_field.files[ 0 ].name;
147 + link = '';
148 + formData.append( 'file[]', upload_field.files[ 0 ] );
149 + } else {
150 + send_request = false;
151 + }
152 + break;
153 + case 'external' :
154 + link = external_field.value;
155 + file = '';
156 + if ( ! link ) {
157 + send_request = false;
158 + }
159 + break;
160 + }
161 + material_data.push( { label, method, file, link } );
162 + } );
163 +
164 + if ( ! send_request ) {
165 + alert( 'Enter file title, choose file or enter file link!' );
166 + } else {
167 + // console.log(material_data);
168 + material_data = JSON.stringify( material_data );
169 + const url = `${ lpGlobalSettings.rest }lp/v1/material/item-materials/${ postID }`;
170 + formData.append( 'data', material_data );
171 + target.classList.add( 'loading' );
172 +
173 + fetch( url, {
174 + method: 'POST',
175 + headers: {
176 + 'X-WP-Nonce': lpGlobalSettings.nonce,
177 + },
178 + body: formData,
179 + } ) // wrapped
180 + .then( ( res ) => res.text() )
181 + .then( ( resString ) => {
182 + // console.log( data );
183 + if ( ! is_single ) {
184 + material__group_container.innerHTML = '';
185 + } else {
186 + materials[ 0 ].remove();
187 + }
188 + const res = JSON.parse( resString );
189 + const { message, data, status } = res;
190 + alert( message );
191 +
192 + if ( status === 'success' ) {
193 + if ( data.length > 0 ) {
194 + const material_table = document.querySelector( '.lp-material--table' );
195 + const thead = material_table.querySelector( 'thead' );
196 + const tbody = material_table.querySelector( 'tbody' );
197 +
198 + thead.classList.remove( 'hidden' );
199 + for ( let i = 0; i < data.length; i++ ) {
200 + const row = data[ i ];
201 + insertRow( tbody, row );
202 + }
203 + can_upload.innerText = parseInt( can_upload.innerText ) - data.length;
204 + add_btn.setAttribute( 'can-upload', can_upload.innerText );
205 + }
206 + }
207 + } )
208 + .finally( () => {
209 + target.classList.remove( 'loading' );
210 + } )
211 + .catch( ( err ) => console.log( err ) );
212 + }
213 + }
214 + }
215 + //delete material
216 + document.addEventListener( 'click', function( e ) {
217 + const target = e.target;
218 + if ( target.classList.contains( 'delete-material-row' ) && target.nodeName == 'A' ) {
219 + const rowID = target.getAttribute( 'data-id' ), //material file ID
220 + message = document.getElementById( 'delete-material-message' ).value;//Delete message content
221 + if ( confirm( message ) ) {
222 + wp.apiFetch( {
223 + path: `lp/v1/material/${ rowID }`,
224 + method: 'DELETE',
225 + data: {
226 + item_id: postID,
227 + },
228 + } ).then( ( res ) => {
229 + // console.log( res );
230 + if ( res.status !== 200 || ! res.delete ) {
231 + alert( res.message );
232 + } else {
233 + target.closest( 'tr' ).remove();
234 + can_upload.innerText = ~~can_upload.innerText + 1;
235 + add_btn.setAttribute( 'can-upload', ~~can_upload.innerText );
236 + }
237 + } ).catch( ( err ) => {
238 + console.log( err );
239 + } ).finally( () => {
240 +
241 + } );
242 + }
243 + }
244 + } );
245 + const singleNode = ( ( nodeList ) => ( node ) => {
246 + const layer = { // define our specific case
247 + 0: { value: node, enumerable: true },
248 + length: { value: 1 },
249 + item: {
250 + value( i ) {
251 + return this[ +i || 0 ];
252 + },
253 + enumerable: true,
254 + },
255 + };
256 + return Object.create( nodeList, layer ); // put our case on top of true NodeList
257 + } )( document.createDocumentFragment().childNodes ); // scope a true NodeList
258 + $( '.lp-material--table tbody' ).sortable( {
259 + items: 'tr',
260 + cursor: 'move',
261 + axis: 'y',
262 + handle: 'td.sort',
263 + scrollSensitivity: 40,
264 + forcePlaceholderSize: true,
265 + helper: 'clone',
266 + opacity: 0.65,
267 + update( event, ui ) {
268 + $( this ).sortable( 'option', 'disabled', true );
269 + updateSort();
270 + $( this ).sortable( 'option', 'disabled', false );
271 + },
272 + } );
273 + function updateSort() {
274 + const items = $( '.lp-material--table tbody tr' ),
275 + data = [];
276 + // $( ".lp-material--table tbody tr" ).sortable( "option", "disabled", true );
277 + items.each( function( i, item ) {
278 + $( this ).attr( 'data-sort', i + 1 );
279 + data.push( { file_id: ~~$( this ).attr( 'data-id' ), orders: i + 1 } );
280 + } );
281 + wp.apiFetch( {
282 + path: `lp/v1/material/item-materials/${ postID }`,
283 + method: 'PUT',
284 + data: {
285 + sort_arr: JSON.stringify( data ),
286 + },
287 + } ).then( ( res ) => {
288 + if ( res.status == 200 ) {
289 + //
290 + } else {
291 + alert( 'Sort table fail.' );
292 + }
293 + } ).catch( ( err ) => {
294 + console.log( err );
295 + } ).finally( () => {
296 +
297 + } );
298 + // $( ".lp-material--table tbody tr" ).sortable( "option", "disabled", false );
299 + // console.log( data );
300 + }
301 +} );