RT 4.2.11, ticket#13852
[freeside.git] / rt / share / static / js / util.js
diff --git a/rt/share/static/js/util.js b/rt/share/static/js/util.js
new file mode 100644 (file)
index 0000000..b665c0e
--- /dev/null
@@ -0,0 +1,345 @@
+/* Visibility */
+
+function show(id) { delClass( id, 'hidden' ) }
+function hide(id) { addClass( id, 'hidden' ) }
+
+function hideshow(id) { return toggleVisibility( id ) }
+function toggleVisibility(id) {
+    var e = jQuery('#' + id);
+
+    if ( e.hasClass('hidden') ) {
+        e.removeClass('hidden');
+    }
+    else {
+        e.addClass('hidden');
+    }
+
+    return false;
+}
+
+function setVisibility(id, visibility) {
+    if ( visibility ) show(id);
+    else hide(id);
+}
+
+function switchVisibility(id1, id2) {
+    // Show both and then hide the one we want
+    show(id1);
+    show(id2);
+    hide(id2);
+    return false;
+}
+
+function toggle_upgrade_history(widget, selector) {
+    jQuery(selector).toggle();
+    jQuery(widget).toggleClass("rolled-up");
+}
+
+/* Classes */
+function jQueryWrap( id ) {
+    return typeof id == 'object' ? jQuery(id) : jQuery('#'+id);
+}
+
+function addClass(id, value) {
+    jQueryWrap(id).addClass(value);
+}
+
+function delClass(id, value) {
+    jQueryWrap(id).removeClass(value);
+}
+
+/* Rollups */
+
+function rollup(id) {
+    var e = jQueryWrap(id);
+    var e2  = e.parent();
+    
+    if (e.hasClass('hidden')) {
+        set_rollup_state(e,e2,'shown');
+        createCookie(id,1,365);
+    }
+    else {
+        set_rollup_state(e,e2,'hidden');
+        createCookie(id,0,365);
+    }
+    return false;
+}
+
+function set_rollup_state(e,e2,state) {
+    if (e && e2) {
+        if (state == 'shown') {
+            show(e);
+            delClass( e2, 'rolled-up' );
+        }
+        else if (state == 'hidden') {
+            hide(e);
+            addClass( e2, 'rolled-up' );
+        }
+    }
+}
+
+/* other utils */
+
+function setCheckbox(input, name, val) {
+    if (val == null) val = input.checked;
+
+    // Find inputs within the current form or collection list, whichever is closest.
+    var container = jQuery(input).closest("form, table.collection-as-table").get(0);
+    var myfield   = container.getElementsByTagName('input');
+    for ( var i = 0; i < myfield.length; i++ ) {
+        if ( myfield[i].type != 'checkbox' ) continue;
+        if ( name ) {
+            if ( name instanceof RegExp ) {
+                if ( ! myfield[i].name.match( name ) ) continue;
+            }
+            else {
+                if ( myfield[i].name != name ) continue;
+            }
+
+        }
+
+        myfield[i].checked = val;
+    }
+}
+
+/* apply callback to nodes or elements */
+
+function walkChildNodes(parent, callback)
+{
+    if( !parent || !parent.childNodes ) return;
+    var list = parent.childNodes;
+    for( var i = 0; i < list.length; i++ ) {
+        callback( list[i] );
+    }
+}
+
+function walkChildElements(parent, callback)
+{
+    walkChildNodes( parent, function(node) {
+        if( node.nodeType != 1 ) return;
+        return callback( node );
+    } );
+}
+
+/* shredder things */
+
+function showShredderPluginTab( plugin )
+{
+    var plugin_tab_id = 'shredder-plugin-'+ plugin +'-tab';
+    var root = jQuery('#shredder-plugin-tabs');
+    
+    root.children(':not(.hidden)').addClass('hidden');
+    root.children('#' + plugin_tab_id).removeClass('hidden');
+
+    if( plugin ) {
+        show('shredder-submit-button');
+    } else {
+        hide('shredder-submit-button');
+    }
+}
+
+function checkAllObjects()
+{
+    var check = jQuery('#shredder-select-all-objects-checkbox').prop('checked');
+    var elements = jQuery('#shredder-search-form :checkbox[name=WipeoutObject]');
+
+    if( check ) {
+        elements.prop('checked', true);
+    } else {
+        elements.prop('checked', false);
+    }
+}
+
+function checkboxToInput(target,checkbox,val){    
+    var tar = jQuery('#' + escapeCssSelector(target));
+    var box = jQuery('#' + escapeCssSelector(checkbox));
+    if(box.prop('checked')){
+        if (tar.val()==''){
+            tar.val(val);
+        }
+        else{
+            tar.val( val+', '+ tar.val() );        
+        }
+    }
+    else{
+        tar.val(tar.val().replace(val+', ',''));
+        tar.val(tar.val().replace(val,''));
+    }
+    jQuery('#UpdateIgnoreAddressCheckboxes').val(true);
+}
+
+// ahah for back compatibility as plugins may still use it
+function ahah( url, id ) {
+    jQuery('#'+id).load(url);
+}
+
+// only for back compatibility, please JQuery() instead
+function doOnLoad( js ) {
+    jQuery(js);
+}
+
+jQuery(function() {
+    var opts = {
+        dateFormat: 'yy-mm-dd',
+        constrainInput: false,
+        showButtonPanel: true,
+        changeMonth: true,
+        changeYear: true,
+        showOtherMonths: true,
+        selectOtherMonths: true
+    };
+    jQuery(".datepicker:not(.withtime)").datepicker(opts);
+    jQuery(".datepicker.withtime").datetimepicker( jQuery.extend({}, opts, {
+        stepHour: 1,
+        // We fake this by snapping below for the minute slider
+        //stepMinute: 5,
+        hourGrid: 6,
+        minuteGrid: 15,
+        showSecond: false,
+        timeFormat: 'HH:mm:ss'
+    }) ).each(function(index, el) {
+        var tp = jQuery.datepicker._get( jQuery.datepicker._getInst(el), 'timepicker');
+        if (!tp) return;
+
+        // Hook after _injectTimePicker so we can modify the minute_slider
+        // right after it's first created
+        tp._base_injectTimePicker = tp._injectTimePicker;
+        tp._injectTimePicker = function() {
+            this._base_injectTimePicker.apply(this, arguments);
+
+            // Now that we have minute_slider, modify it to be stepped for mouse movements
+            var slider = jQuery.data(this.minute_slider[0], "ui-slider");
+            slider._base_normValueFromMouse = slider._normValueFromMouse;
+            slider._normValueFromMouse = function() {
+                var value           = this._base_normValueFromMouse.apply(this, arguments);
+                var old_step        = this.options.step;
+                this.options.step   = 5;
+                var aligned         = this._trimAlignValue( value );
+                this.options.step   = old_step;
+                return aligned;
+            };
+        };
+    });
+});
+
+function textToHTML(value) {
+    return value.replace(/&/g,    "&amp;")
+                .replace(/</g,    "&lt;")
+                .replace(/>/g,    "&gt;")
+                .replace(/-- \n/g,"--&nbsp;\n")
+                .replace(/\n/g,   "\n<br />");
+};
+
+CKEDITOR_BASEPATH=RT.Config.WebPath + "/static/RichText/";
+function ReplaceAllTextareas() {
+    var sAgent = navigator.userAgent.toLowerCase();
+    if (!CKEDITOR.env.isCompatible ||
+        sAgent.indexOf('iphone') != -1 ||
+        sAgent.indexOf('ipad') != -1 ||
+        sAgent.indexOf('android') != -1 )
+        return false;
+
+    // replace all content and signature message boxes
+    var allTextAreas = document.getElementsByTagName("textarea");
+
+    for (var i=0; i < allTextAreas.length; i++) {
+        var textArea = allTextAreas[i];
+        if (jQuery(textArea).hasClass("messagebox richtext")) {
+            // Turn the original plain text content into HTML
+            var type = jQuery("#"+textArea.name+"Type");
+            if (type.val() != "text/html")
+                textArea.value = textToHTML(textArea.value);
+
+            // Set the type
+            type.val("text/html");
+
+            CKEDITOR.replace(textArea.name,{ width: '100%', height: RT.Config.MessageBoxRichTextHeight });
+
+            jQuery("#" + textArea.name + "___Frame").addClass("richtext-editor");
+        }
+    }
+};
+
+function toggle_addprincipal_validity(input, good, title) {
+    if (good) {
+        jQuery(input).nextAll(".warning").hide();
+        jQuery("#acl-AddPrincipal input[type=checkbox]").removeAttr("disabled");
+    } else {
+        jQuery(input).nextAll(".warning").css("display", "block");
+        jQuery("#acl-AddPrincipal input[type=checkbox]").attr("disabled", "disabled");
+    }
+
+    if (title == null)
+        title = jQuery(input).val();
+
+    update_addprincipal_title( title );
+}
+
+function update_addprincipal_title(title) {
+    var h3 = jQuery("#acl-AddPrincipal h3");
+    h3.html( h3.text().replace(/: .*$/,'') + ": " + title );
+}
+
+// when a value is selected from the autocompleter
+function addprincipal_onselect(ev, ui) {
+
+    // if principal link exists, we shall go there instead
+    var principal_link = jQuery(ev.target).closest('form').find('ul.ui-tabs-nav a[href="#acl-' + ui.item.id + '"]:first');
+    if (principal_link.size()) {
+        jQuery(this).val('').blur();
+        update_addprincipal_title( '' ); // reset title to blank for #acl-AddPrincipal
+        principal_link.click();
+        return false;
+    }
+
+    // pass the item's value along as the title since the input's value
+    // isn't actually updated yet
+    toggle_addprincipal_validity(this, true, ui.item.value);
+}
+
+// when the input is actually changed, through typing or autocomplete
+function addprincipal_onchange(ev, ui) {
+    // if we have a ui.item, then they selected from autocomplete and it's good
+    if (!ui.item) {
+        var input = jQuery(this);
+        // Check using the same autocomplete source if the value typed would
+        // have been autocompleted and is therefore valid
+        jQuery.ajax({
+            url: input.autocomplete("option", "source"),
+            data: {
+                op: "=",
+                term: input.val()
+            },
+            dataType: "json",
+            success: function(data) {
+                if (data)
+                    toggle_addprincipal_validity(input, data.length ? true : false );
+                else
+                    toggle_addprincipal_validity(input, true);
+            }
+        });
+    } else {
+        toggle_addprincipal_validity(this, true);
+    }
+}
+
+
+function escapeCssSelector(str) {
+    return str.replace(/([^A-Za-z0-9_-])/g,'\\$1');
+}
+
+
+jQuery(function() {
+    jQuery(".user-accordion").each(function(){
+        jQuery(this).accordion({
+            active: (jQuery(this).find("h3").length == 1 ? 0 : false),
+            collapsible: true,
+            heightStyle: "content",
+            header: "h3"
+        }).find("h3 a.user-summary").click(function(ev){
+            ev.stopPropagation();
+            return true;
+        });
+    });
+    ReplaceAllTextareas();
+});