CSS3按钮Jquery控制面板 - 背景图像和内部阴影

时间:2013-11-25 15:09:22

标签: jquery css3

我尝试实现背景图像css规则(禁用所有“背景图像”规则并添加新规则“background-image:url(image.png)”)和来自此CP的css3内部阴影:

var css3 = {
  target: "#button-container > div", /* The tag to be styled */
  container: "#accordion",         /* The container of all controls */
  buttonCss: "#button-css",        /* Element that holds normal CSS */
  hoverCss: "#hover-css",          /* Element that holds :hover CSS */
  live: "#live-css",               /* Element that holds live stylesheet */
  liveIndex: 0, // Will be calculated as the last stylesheet
  initialHover: "",
  initialButton: "",


  handlers: {

    'button-label': function(ev) {
      $(css3.target).html(this.value);
    },

    'background': function(ev) {
      if (this.disabled) {
        css3.updateCss('background-image: -webkit-linear-gradient', value, null, '');
        css3.updateCss('background-image: -moz-linear-gradient', value, null, '');
        css3.updateCss('background-image: -ms-linear-gradient', value, null, '');
        css3.updateCss('background-image: -o-linear-gradient', value, null, '');
        css3.updateCss('background-image: linear-gradient', value, null, '');
        css3.updateCss('background-color', '');
        return; // And we're done
      }
      // First, update flat background for flat and as fallback for gradient
      css3.updateCss('background-color', $(this).val());

      if (!($('#background-radio').prop('checked'))) { // If true it's flat

        if ($('#gradient-type').val() == 'linear') {
          var value = '(' + $('#gradient-angle').val() + 'deg, '
                    + $('#end-color').val() + ', '
                    + $(this).val() + ')'
          css3.updateCss('background-image: -webkit-linear-gradient', value, null, '');
          css3.updateCss('background-image: -moz-linear-gradient', value, null, '');
          css3.updateCss('background-image: -ms-linear-gradient', value, null, '');
          css3.updateCss('background-image: -o-linear-gradient', value, null, '');
          css3.updateCss('background-image: linear-gradient', value, null, '');
          // filter: progid:DXImageTransform.Microsoft.Gradient()
        } else { // Radial
          var value = '(center ' + $('#gradient-angle').val() + 'deg, circle '
                    + $('#gradient-size').val() + ', '
                    + $('#end-color').val() + ', '
                    + $(this).val() + ')'
          css3.updateCss('background-image: -webkit-radial-gradient', value, null, '');
          css3.updateCss('background-image: -moz-radial-gradient', value, null, '');
          css3.updateCss('background-image: -ms-radial-gradient', value, null, '');
          // Opera can't do radial gradients yet and when it can, it'll support the standard
          css3.updateCss('background-image: radial-gradient', value, null, '');
        }
      }
    },

    'tranforms-target-controls': {
      'rotate': '#transform',
      'skew':   '#transform-skew',
      'skewX':  '#transform-skew-x',
      'skewY':  '#transform-skew-y',
      'scale':  '#transform-scale',
      'scaleX': '#transform-scale-x',
      'scaleY': '#transform-scale-y'
    }, // Defined outside the next function so it only gets created once
    'transform': function(ev) {
      // filter: progid:DXImageTransform.Microsoft.Matrix(/* IE6â“IE9 /) 

      var value = '';
      for (var trans in css3.handlers['tranforms-target-controls']) {
        var ctrl = $(css3.handlers['tranforms-target-controls'][trans]);
        if (!($(ctrl).attr('disabled'))) {
          value += trans + '(' + $(ctrl).val() + ($(ctrl).attr('units') || '') + ') '; 
        }
      }
      value = $.trim(value);
      var comp = $(this).attr('compat');
      if (comp) {
        var vals = comp.split(',');
        for (var i = vals.length - 1; i >= 0; i--) {
          css3.updateCss(vals[i], value);
        } 
      }
      css3.updateCss('transform', value);
    },

    'transition': function(ev) {
      var en = $(this).attr('disabled');
      var newVal = en ? '' : css3.getValue(this);
      var prop = 'transition';
      var compOpt = en && ($('#transition').children(':selected').attr('compat') == 'true');
      css3.updateCss(prop, newVal, css3.buttonCss);
      var comp = $(this).attr('compat');
      if (comp) {
        var vals = comp.split(',');
        for (var i = vals.length - 1; i >= 0; i--) {
          css3.updateCss(vals[i] + prop, (compOpt ? vals[i] : '') + newVal, css3.buttonCss);
        } 
      }
    } // END handlers
  },

  /**
   * Event handler for most controls.
   * Builds and updates the CSS for the control.
   * Iterates over any alternative tags found.
   */ 
  genericHandler: function(ev) {
    if (!this.id) { return; }
    var newVal = css3.getValue(this);
    css3.updateCss(this.id, newVal);
    var comp = $(this).attr('compat');
    if (comp) {
      var vals = comp.split(',');
      for (var i = vals.length - 1; i >= 0; i--) {
        css3.updateCss(vals[i], newVal);
      } 
    }
  },


  /**
   * Code to parse CSS to get value
   */
  parsers: {
    'background-image': function(attr, val) {
      var initial = val.substr(0,1);
      if (initial == '-') { return; } // Ignore client specific

      var el = $('#background');
      var gr = $('#gradient-type');
      if($(el).attr('disabled')) {
        css3.disable($(el), false, false);
        $(el).prevAll('input').prop('checked', true);
      }
      $('#background-radio').nextAll('input').prop('checked', true);

      if (initial == 'l') { // Linear Gradient
        $(gr).val('linear').change();
        var vals = val.slice(val.indexOf('(') + 1, val.indexOf(')')).split(',')
        css3.setValue('#gradient-angle', vals[0]);
        css3.setValue('#end-color', jQuery.trim(vals[1]));
        css3.setValue(el, jQuery.trim(vals[2]));

      } else if (initial == 'r') { // Radial Gradient
        $(gr).val('radial').change();
        var vals = val.slice(val.indexOf('(') + 1, val.indexOf(')')).split(',')
        var subV = vals[0].split(' ');
        css3.setValue('#gradient-angle', subV[1]);
        var subV = vals[1].split(' ');
        css3.setValue('#radial-gradient-size', subV[1]);
        css3.setValue('#end-color', jQuery.trim(vals[2]));
        css3.setValue(el, jQuery.trim(vals[3]));
      }
      $('#gradient-angle').keyup();
      $('#end-color').keyup();
      $('#background-radio').nextAll('input').click();
      $(el).keyup();
    },

    'background-color': function(attr, val) {
      var el = $('#background');
      if($(el).attr('disabled')) {
        css3.disable($(el), false, false);
        $(el).prevAll('input').prop('checked', true);
        $('#background-radio').prop('checked', true);
        css3.setValue(el, val);
        $(el).keyup();
      }
    },

    'transform': function(attr, val) {
      var el, sub, vals = val.split(' ');
      for (var i = vals.length - 1; i >= 0; i--) {
        sub = vals[i].split('(');
        el = $(css3.handlers['tranforms-target-controls'][sub[0]]);
        css3.disable(el, false, false);
        $(el).prevAll('input[type="checkbox"]').prop('checked', true);
        css3.setValue(el, sub[1]);
      }
    }
  },

  /**
   * If a trimmed line from the CSS parse starts with anything
   * listed here, ignore the line.
   */  
  parseIgnore: ['}', '.button', '-'],

  /**
   * Generic code to parse CSS and set the appropriate
   * value in the appropriate control
   */
  genericParser: function(attr, val) {
    var el = $('#' + attr);
    var args, vals;
    if (args = $(el).attr('args')) {
      vals = val.split(' ');
      for (var i = vals.length - 1; i > 0; i--) {
        css3.setValue('#' + attr + '-' + i, vals[i]);
        $('#' + attr + '-' + i).keyup();
      }
      css3.setValue('#' + attr, vals[0]);
    } else {
      css3.setValue(el, val);
    }
    css3.disable($(el), false, false);
    $(el).prevAll('input').prop('checked', true);
    $(el).keyup();
    if ($(el).parent().parent().hasClass('more')) {
      css3.parseToggleMore(el);
    }
  },

  /**
   * Cleanly parse and set value
   */
  setValue: function(el, val) {
    if ($(el).parent().hasClass('numeric')) {
      val = parseFloat(val); // Strip any units
    }
    $(el).val(val);
  },

  /**
   * Parse the CSS found in the target element
   */
  parseCss: function(trg) {
    // Disable everything except transitions in the control panel
    var transState = $('#transition').prevAll('input').prop('checked');
    $('#accordion').find('input[type="text"], select').each(function(idx, el) {
      if (!($(el).attr('id') == 'transition' || $(el).attr('arg') == 'transition'
        || $(el).attr('id') == 'button-label')) {
        css3.disable(el, true, false);
      }
    });
    // Enable and uncheck all the disable checkboxes
    $('#accordion').find('input[type="checkbox"]').each(function(idx, el) {
      $(el).prop('checked', false).attr('disabled', false);
    });
    $('#transition').prevAll('input').prop('checked', transState);


    if (trg === null || typeof(trg) === 'undefined') {
      trg = ($('#target-hover').prop('checked') ? css3.hoverCss : css3.buttonCss);
    }
    var parts, func, line, lines = $(trg).html().split("\n");

    linesLoop: 
    for (var i = lines.length -1; i >= 0; i--) {
      line = jQuery.trim(lines[i]);
      if (line.length == 0) {
        continue linesLoop; // Skip the line
      }
      for(var x in css3.parseIgnore) {
        if (line.indexOf(css3.parseIgnore[x]) === 0) {
          continue linesLoop; // Skip the line
        }
      }
      parts = line.split(': ');
      parts[1] = jQuery.trim(parts[1].substr(0, parts[1].length - 1)); 
      func = css3.parsers[parts[0]] || css3.genericParser;
      func(parts[0], parts[1]);
    }
  },

  /**
   * Handle change events for an argument field
   */
  argHandler: function(ev) {
    $('#' + $(this).attr('arg')).change();
  },

  /**
   * Build the new value for the elements CSS attribute.
   * Appends units to numeric elements (default 'px').
   * Finds additional arguments to the element if marked.
   */
  getValue: function(el) {
    var val = $(el).val();
    var argCount 
    if ($(el).parent().hasClass('numeric')) {
      val += $(el).attr('units') ? $(el).attr('units') : 'px';
    }
    if (argCount = $(el).attr('args')) {
      for (i = 1; i <= argCount; i++) {
        val += " " + css3.getValue($('#' + $(el).attr('id') + '-' + i));
      }
    }
    return val;
  },

  /**
   * Disable or enable everything inside the element.
   */  
  disable: function(el, disable, css) {
    if (typeof(css) === 'undefined') { css = true; }
    if (typeof(disable) === 'undefined') { disable = true; }
    var cont = $(el).parent();
    $(cont).children('input, select').each(function(idx, ctrl) {
      $(ctrl).attr('disabled', disable);
      var argCount;
      if (argCount = $(ctrl).attr('args')) {
        for (var i = 1; i <= argCount; i++) {
          css3.disable($('#' + ctrl.id + '-' + i), disable);
        }
      }
    });
    if (disable) {
      $(cont).addClass('disabled');
      $(cont).children('.ui-slider').slider('disable');
    } else {
      $(cont).removeClass('disabled');
      $(cont).children('.ui-slider').slider('enable');
    }
    // Finally, remove associated CSS class
    if (css && $(el).attr('id') && !$(el).attr('arg')) {
      var newVal = disable ? false : css3.getValue(el);
      css3.updateCss($(el).attr('id'), newVal);

      var comp = $(el).attr('compat');
      if (comp) {
        var vals = comp.split(',');
        for (var i = vals.length - 1; i >= 0; i--) {
          css3.updateCss(vals[i], newVal);
        } 
      }
    }
    // Special case for transforms
    if ($(el).parents('#transform-container').length) {
      $('#' + ($(el).attr('arg') || $(el).attr('id'))).keyup();
    }
  },

  /**
   * Disable or enable everything inside the element
   * that contains this checkbox except the checkbox.
   */  
  disableHandler: function(ev) {
    css3.disable($(this).nextAll('input, select'), !this.checked);
    $(this).attr('disabled', false);
  },

  /**
   * Publish the current contents of the style blocks into stylesheet.
   * Most browsers can do this using the innerHTML, as used by jQuery .html(),
   * but IE can't, it uses it's own cssText property of the stylesheet Object.
   */
  updateCodeBlock: function() {
    var newVal = $(css3.buttonCss).html() + $(css3.hoverCss).html();

    if (typeof(document.styleSheets[0].cssText) === 'undefined') {
      $(css3.live).html(newVal);
    } else {
      document.styleSheets[css3.liveIndex].cssText = newVal;
    }
  },


  /**
   * Work around a bug in IE that causes "HTML normalization" when making
   * changes to <PRE> elements using innerHTML.
   * See: http://www.quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html
   * Essentially, this bug causes IE to strip newline characters, making
   * all the code appear on one line and breaking the parsers here.
   * The work around is to use the IE proprietary outerHTML if available.
   */
  pushCssChanges: function(target, value) {
    var attr = $(target).attr('outerHTML');
    if (typeof attr === 'undefined' || attr === false) {
      $(target).html(value); // Good browser will do this.
    } else { // Do something crazy for IE
      var tag = $(target).attr('tagName').toLowerCase();
      var id = $(target).attr('id');
      $(target).attr('outerHTML',
        '<' + tag + ' id="' + id + '">' +
        value + '</' + tag + '>'
      );
    }
  },


  /**
   * Update an attribute in the style block with the specified value.
   * TODO If the attribute is not present, add it.
   * TODO If val is empty, remove the attribute.
   *
   * string attr  The name of the css attribute
   * string val   The new value
   * string trg   (optional) target element. Will be calculated is missing.
   ( string div   (optional) divider between attr and val (default = ': ');
   */ 
  updateCss: function(attr, val, trg, div) {
    if (trg === null || typeof(trg) === 'undefined') {
      trg = ($('#target-hover').prop('checked') ? css3.hoverCss : css3.buttonCss);
    }
    if (typeof(div) === 'undefined') { div = ": "; }

    var rex = new RegExp("\\s+" + attr + div + "(.+);");
    var rep = val ? "\n  " + attr + div + val + ";" : "";
    var subject = $(trg).html();
    if (subject.search(rex) > 0) {
      // If the search string exists, replace it, even if replacement is blank
      css3.pushCssChanges(trg, subject.replace(rex, rep));
    } else if (val) {
      // If the search string doesn't exist and we have a value,
      // iterate all lines and add new line in alphabetical order.
      var lines = subject.split("\n");
      var i, first, offset = 0;
      for (i = 0; i < lines.length; i++) {
        first = lines[i].substr(0,1);
        if ((lines[i].length == 0 || first != ' '
          || $.trim(lines[i]) < $.trim(rep))
          && first != '}') {
          offset += lines[i].length;
        } else {
          break;
        }
      }
      offset += --i; // Account for the newlines (except the last one)
      css3.pushCssChanges(trg, subject.substr(0, offset) + rep + subject.substr(offset));
    }
    css3.updateCodeBlock();
  },

  toggleMore: function(ev) {
    var trg = '#' + $(this).attr('id') + '-area';
    var disable = $(this).hasClass('ui-icon-minus'); 
    if(disable) {
      $(this).addClass('ui-icon-plus').removeClass('ui-icon-minus');
      $(trg).slideUp()
    } else {
      $(this).removeClass('ui-icon-plus').addClass('ui-icon-minus');
      $(trg).slideDown()
    }
    $(trg + ' > div > input, ' + trg + ' > div > select').each(function(idx, el) {
      css3.disable(el, disable);
      $(el).prevAll('input[type="checkbox"]').prop('checked', true);
    });
    $(this).prevAll('input[type="checkbox"]').prop('checked', disable);
    css3.disable($(this).prevAll('input[type="text"], select'), !disable);
  },

  /**
   * Runs for every control inside a "more" area on CSS parse.
   * Call toggle more to open area containing el.
   */
  parseToggleMore: function(el) {
    var cont = $(el).parent().parent();
    var trg = '#' + $(cont).attr('id').replace('-area', '');
    $(trg).removeClass('ui-icon-plus').addClass('ui-icon-minus');
    $(cont).slideDown();
    $(trg).prevAll('input[type="checkbox"]').attr('disabled', true);
  }
}; // END css3


$(document).ready(function() {
  var ccss = $('.button').attr('style').split(';').join(";\n ");
            console.log(ccss);
            $('#button-css').html('\n.button {\n '+ccss+'}');
  css3.liveIndex = document.styleSheets.length - 1;
  $(css3.container).accordion({autoHeight: false, active:1});
  css3.updateCodeBlock();

  /**
   * Add handler to gradient-type before generic handlers are added
   */
  $('#gradient-type').change(function(ev) {
    css3.disable($('#gradient-size'), $(this).val() == 'linear');
    for (var i = 0; i < 5; i++) {
      css3.updateCss('background-image');
    }
  });

  /**
   * Create color pickers for all color class controls
   */
  $('.color input[type="text"]').each(function(idx, el) {
    var div = $(document.createElement('div')).attr({id: el.id + '-picker'});
    $(el).parent().append(div);
    $(div).hide();

    $(div).bind('delayHide', function() {
      this.timeId = null;
      $(this).hide();
    });

    /* Mouse position tracking used here because IE causes the
     * textbox to lose focus when you click on the colour picker
     * which hides it if we use the focus events.
     * It works in all other browser, but we have to do it the
     * complicated way below for IE up to 9! */

    $(el).click(function(ev) {
      $('#' + this.id + '-picker').show();
    });
    $(el).mouseleave(function(ev) {
      $(div).mouseleave();
    });
    $(el).mouseenter(function(ev) {
      $(div).mouseenter();
    });
    $(div).mouseleave(function(ev) {
      this.timeId = window.setTimeout(function() { $(div).trigger('delayHide'); }, 100);
    });
    $(div).mouseenter(function(ev) {
      if (this.timeId) {
        window.clearTimeout(this.timeId);
        this.timeId = null;
      }
    });

    $(div).farbtastic(el);
  });

  /**
   * Create sliders for all numeric controls
   */
  $('.numeric input[type="text"]').each(function(idx, el) {
    var div = $(document.createElement('div')).attr({id: el.id + '-slider'});
    var opts = { value: el.value || 0 };
    var rangeCode = $(el).attr('range');
    if (rangeCode) {
      var ranges = rangeCode.split(',');
      switch(ranges.length) {
      case 3: opts.step = parseFloat(ranges[2]);
      case 2: opts.max = parseFloat(ranges[1]);
      case 1: opts.min = parseFloat(ranges[0]);
      default: break;
      }
    }
    $(el).parent().append(div);
    $(div).slider(opts);
    div.attr("associate", el.id);
    el.associate = div;
    $(div).bind('slide', function(ev, ui) {
      // Get associated element and set it's value to slider value
      var el = $('#' + $(this).attr("associate"))
      $(el).prop("value", $(this).slider("value"));
      $(el).keyup();
    });
    $(el).bind('change', function(ev) {
      // Get associated slider and set it's value to current value
      $(this.associate).slider("value", this.value);
    });
  });

  /**
   * Set any marked regions as disabled
   */
  $('.disabled input[type="text"], .disabled select').each(function(idx, el) {
    css3.disable(el);
  });
  $('.disabled .ui-slider').each(function(idx, el) {
    $(el).slider('disable');
  });

  /**
   * Assign event handlers to all input elements in settings container
   */
  $(css3.container + ' input, ' + css3.container + ' select').each(function(idx, el) {
    var func;
    if (css3.handlers[el.id]) {
      func = css3.handlers[el.id];
    } else if ($(el).attr('arg')) {
      func = css3.argHandler;
    } else {
      func = css3.genericHandler;
    }
    $(el).bind('change', func);
    $(el).bind('keyup', function(ev) { $(this).change(); });
  });

  /**
   * Add check boxes to all toggle areas
   */
  $('.toggle').each(function(idx, el) {
    var chk = $('<input/>').attr('type', 'checkbox');
    $(el).prepend(chk);
    $(chk).bind('click', css3.disableHandler);
    $(chk).prop('checked', true);
    if ($(el).hasClass('disabled')) {
      $(chk).prop('checked', false);
    }
  });

  /**
   * Assign special handlers
   */
  $('#padding-more').bind('click', function(ev) {
    var newVal = $('#padding').val();
    $('#padding-top').val(newVal).keyup();
    $('#padding-right').val(newVal).keyup();
    $('#padding-bottom').val(newVal).keyup();
    $('#padding-left').val(newVal).keyup();
  });

  $('#border-more').bind('click', function(ev) {
    var newVal = $('#border').val();
    $('#border-top-width').val(newVal).keyup();
    $('#border-right-width').val(newVal).keyup();
    $('#border-bottom-width').val(newVal).keyup();
    $('#border-left-width').val(newVal).keyup();
    newVal = $('#border-1').val();
    $('#border-top-style').val(newVal).keyup();
    $('#border-right-style').val(newVal).keyup();
    $('#border-bottom-style').val(newVal).keyup();
    $('#border-left-style').val(newVal).keyup();
    newVal = $('#border-2').val();
    $('#border-top-color').val(newVal).keyup();
    $('#border-right-color').val(newVal).keyup();
    $('#border-bottom-color').val(newVal).keyup();
    $('#border-left-color').val(newVal).keyup();
    css3.disable($('#border'), $(this).hasClass('ui-icon-plus'));
  });

  $('input[name="background-radio"]').click(function(ev) {
    // If we've changed to flat mode, clear out all five background-images
    if ($('#background-radio').prop('checked') // If true it's flat
      ||$('#background-radio').attr('disabled')) {
      for (var i = 0; i < 5; i++) {
        css3.updateCss('background-image');
      }
      css3.disable($('#gradient-angle'), true, false);
      css3.disable($('#gradient-size'), true, false);
      css3.disable($('#gradient-type'), true, false);
      css3.disable($('#end-color'), true, false);
    } else {
      css3.disable($('#gradient-angle'), false, false);
      css3.disable($('#gradient-type').change(), false, false);
      css3.disable($('#end-color'), false, false);
    }
  });

  $('#background-container input[type="checkbox"]').each(function(idx, el) {
    $(el).attr('disabled', false);
    $(el).parent().addClass('toggle');
    $(el).click(function(ev) {
      css3.disable($(this).parent().parent().find('input, select'), !this.checked, false);
      $(this).attr('disabled', false);
      $('#background-radio').click();
      $('#background').change();
    });
  });

  $('#transition-container input[type="checkbox"]').each(function(idx, el) {
    $(el).attr('disabled', false);
    $(el).parent().addClass('toggle');
    $(el).click(function(ev) {
      css3.disable($('#transition'), !this.checked, false);
      $(this).attr('disabled', false);
      $('#transition').change();
    });
  });

  /**
   * Store initial content of CSS blocks so we can reset later
   */
  css3.initialHover = $(css3.hoverCss ).get(0).innerHTML;
  css3.initialButton = $(css3.buttonCss).get(0).innerHTML;

  /**
   * Reset button overwrites current with stored content then re-parses
   */ 
  $('#sub-content > input[value="Reset"]').click(function(ev) {
    var trg;
    var cnt;
    if ($('#target-hover').prop('checked')) {
      trg = css3.hoverCss;
      cnt = css3.initialHover;
    } else {
      trg = css3.buttonCss;
      cnt = css3.initialButton;
    }
    css3.pushCssChanges(trg, cnt);
    css3.parseCss(trg);
  });

  $('#target-hover').click(function(ev) {
    css3.parseCss(($(this).prop('checked') ? css3.hoverCss : css3.buttonCss));
  });

  /**
   * Activate all more toggles
   */
  $('.more-toggle').each(function(idx, el) {
    $(el).bind('click', css3.toggleMore);
  });

  /**
   * Stupid z-index fix for stupid IE. Allows the colour picker to display.
   */
  var zIndexNumber = 10000;
  $('div').each(function() {
    $(this).css('zIndex', zIndexNumber);
    zIndexNumber -= 10;
  });
  $('.farbtastic').each(function() {$(this).css('zIndex', '10010');});
  $('.farbtastic > div').each(function() {$(this).css('zIndex', 'auto');});

  /**
   * Lastly, set interface back to initial settings
   */
  $('#target-hover').prop('checked', false);

  css3.parseCss(css3.buttonCss);
});

Psease检查完整代码http://jsfiddle.net/h73f6/6/

1.Background image url

2.Inner shadow

0 个答案:

没有答案