/*!
* PlaneUI v0.1.0
* @file planeui.js
* @description The Modern HTML5 Cross-Device Responsive Front-end UI Framework.
* @license MIT License
* @author Pandao
* {@link https://github.com/pandao/planeui}
* @updateTime 2015-06-27
*/
(function(factory) {
"use strict";
if(typeof exports === "object" && typeof module === "object")
{
module.exports = factory();
}
else if(typeof define === "function" && (define.amd || define.cmd))
{
define(factory);
}
else
{
window.PUI = window.PlaneUI = window.$ = factory();
}
})(function() {
(function(window, $) {
var PlaneUI = PUI = $;
PlaneUI.extend({
version : "0.1.0",
homePage : "https://github.com/pandao/planeui",
dialogIndex : 1000,
getPixelRatio : function(context) {
var backingStore = context.backingStorePixelRatio ||
context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1;
return (window.devicePixelRatio || 1) / backingStore;
},
mouseOrTouch : function(mouseType, touchType) {
mouseType = mouseType || "click";
touchType = touchType || "touchend";
var eventType = mouseType;
try {
document.createEvent("TouchEvent");
eventType = touchType;
}
catch(e) {}
return eventType;
},
clickOrTouch : function(touchType) {
return this.mouseOrTouch("click", touchType);
},
contextMenuOrTouch : function() {
return this.mouseOrTouch("contextmenu", "touchend");
},
jsonEncode : function(json) {
return JSON.stringify(json);
},
jsonDecode : function(json) {
return JSON.parse(json);
},
support : {
touchEvent : function() {
try {
document.createEvent("TouchEvent");
return true;
} catch(e) {
return false;
}
},
canvas : function() {
try {
document.createElement('canvas').getContext('2d');
return true;
} catch(e) {
return false;
}
},
worker : function() {
return (typeof(Worker) == "undefined") ? false : true;
},
placeholder : function() {
return ('placeholder' in document.createElement('input'));
}
},
responsive : {
xs : function() {
return ($(window).width() < 640);
},
sm : function() {
return ($(window).width() >= 640 && $(window).width() < 768);
},
md : function() {
return ($(window).width() >= 768 && $(window).width() < 992);
},
lg : function() {
return ($(window).width() >= 992 && $(window).width() < 1200);
},
xl : function() {
return ($(window).width() >= 1200 && $(window).width() < 1400);
},
xxl : function() {
return ($(window).width() >= 1400);
}
}
});
window.PUI = window.PlaneUI = window.$ = PlaneUI;
$(function() {
$("*").bind("touchstart", function(e) {
$(this).addClass("hover");
}).bind("touchcancel touchend", function() {
$(this).removeClass("hover");
});
$("a").click(function() {
$(this).blur();
});
});
})(window, jQuery);
(function ($) {
$(function() {
$('.pui-button-sheets-more').each(function() {
var $this = $(this);
$this.bind($.clickOrTouch(), function() {
var parent = $this.parent();
var parentNext = parent.next();
var moreHeight = parent.parent().attr('pui-button-sheets-show-more-height');
parent.parent().height(moreHeight);
parentNext.fadeIn(1000);
var alternate = parentNext.find('a').eq(0);
parentNext.append(' ');
parent.append(alternate);
$this.remove();
});
});
});
})(PlaneUI);
(function ($) {
$(function() {
$("pui-checkbox").each(function(i) {
var $this = $(this);
var checkbox = $(' ');
checkbox.attr("name", $this.attr('name'));
checkbox.val($this.attr('value'));
if($this.hasClass('checked'))
{
checkbox.attr("checked", "checked");
}
if($this.attr('disabled') == "disabled")
{
checkbox.attr("disabled", "disabled");
}
$this.append(checkbox);
$this.bind($.clickOrTouch(), function() {
if($(this).attr('disabled') == "disabled") return ;
$(this).toggleClass('checked');
var input = $(this).find('input');
if(input.attr('checked') == 'checked')
{
input.removeAttr('checked');
}
else
{
input.attr('checked', 'checked');
}
});
});
$("[checkbox-checked-all]").bind($.clickOrTouch(), function() {
var name = $(this).attr("checkbox-checked-all");
$("[name='"+name+"']").each(function() {
if($(this).attr('disabled') != "disabled") {
$(this).addClass("checked");
var input = $(this).find('input');
input.attr('checked', 'checked');
}
});
});
$("[checkbox-cancel]").bind($.clickOrTouch(), function() {
var name = $(this).attr("checkbox-cancel");
$("[name='"+name+"']").each(function() {
if($(this).attr('disabled') != "disabled") {
$(this).removeClass("checked");
var input = $(this).find('input');
input.removeAttr('checked');
}
});
});
$("[checkbox-inverse]").bind($.clickOrTouch(), function() {
var name = $(this).attr("checkbox-inverse");
$("[name='"+name+"']").each(function() {
if($(this).attr('disabled') != "disabled") {
var input = $(this).find('input');
if($(this).attr("class") == "checked") {
$(this).removeClass("checked");
input.removeAttr('checked');
} else {
$(this).addClass("checked");
input.attr('checked', 'checked');
}
}
});
});
});
})(PlaneUI);
(function($) {
function colorPicker(options) {
options = options || {};
var defaults = {
path : "",
width : "",
height : ""
};
var $this = $(this);
var settings = $.extend(defaults, options);
$.getJSON(settings.path + "dist/data/material.design.colors.json", function(json) {
var colorList = [];
var nameList = [];
var sheet = "";
for (var i in json)
{
for (var x in json[i])
{
var name = i + ((x == 500) ? "" : "-" + x);
var color = json[i][x];
if (color) {
nameList.push(name);
colorList.push(color);
sheet += ' ';
}
}
}
var total = nameList.length;
$this.each(function() {
var wrap = '
');
this.target = $dialog;
$dialog.hide();
this.mask({
show : settings.mask,
fixed : settings.fixed,
color : settings.maskColor,
style : settings.maskStyle,
zIndex : settings.zIndex - 1,
opacity : settings.maskOpacity
});
$("body").append($dialog);
$dialog.attr({
id : settings.id,
type : settings.type
});
if(settings.radius) $dialog.addClass('pui-radius');
var type = settings.type;
this.signleCloseBtn = '
';
this.header(settings.header);
this.content({
url : settings.url,
from : settings.from,
padding : settings.padding,
content : settings.content,
buttons : settings.buttons
});
this.footer(settings.footer);
this.width(settings.width);
this.height(settings.height);
this.fixed(settings.fixed);
this.zIndex(settings.zIndex);
this.toolbar(settings.toolbar);
$dialog.css(settings.style).addClass(settings.addClass);
this.show();
if (settings.drag)
{
var dragTarget = $dialog.children(settings.dragTarget);
/*if (settings.dragEvent === "all" || settings.dragEvent === "touch")
{
dragTarget.touchDraggable({
parent : true
});
}*/
$dialog.draggable({
target : dragTarget,
parent : true,
touch : (settings.dragEvent === "all" || settings.dragEvent === "touch") ? true : false
});
}
if (/(iPad|iPhone|iPod)/.test(navigator.userAgent))
{
$dialog.children("section.has-iframe").css("overflow", "auto");
$dialog.children("section").bind("touchmove", function(event) {
$("html, body").css("overflow", "hidden");
event.stopPropagation();
});
}
$(".pui-dialog > *").bind($.clickOrTouch(), function() {
$.dialogIndex ++;
$(this).parent().css("zIndex", $.dialogIndex);
});
$dialog.bind('dialog.reset', function() {
_this.reset(_this.onreset);
});
$(window).resize(function(){
$dialog.trigger('dialog.reset');
});
$.dialogIndex++;
dialog.list[this.id] = this;
this.timeout(settings.timeout);
return this;
};
dialog.proxy = function(func) {
var self = this;
return (function() {
return func.apply(self, arguments);
});
};
dialog.creater.fn = dialog.creater.prototype = {
proxy : dialog.proxy,
status : "",
parent : "",
children : "",
title : function(title) {
var settings = this.settings;
var target = this.target;
if(this.type == "window" || this.type == "iframe")
{
var _header = target.children('header');
var hasHeader = (_header.length > 0);
var title = (title || settings.title) || (_header.find("strong").text() || "");
_header.find('strong').html(title);
}
return this;
},
lockScreen : function(lock) {
$('body,html').css('overflow', (lock) ? 'hidden' : '');
},
mask : function(options) {
var settings = this.settings;
var target = this.target;
if(options.show)
{
var color = options.color || "#000";
var opacity = (typeof options.opacity == "number") ? options.opacity : 0.5;
var style = options.style || {};
var fixed = options.fixed || true;
var id = this.id + '-mask';
var hasMask = ($("#"+id).length > 0);
var mask = (hasMask) ? $("#"+id) : $('
');
if(options.fixed) mask.addClass('pui-mask-fixed');
mask.hide();
mask.css({
backgroundColor : color,
zIndex: options.zIndex || ($.dialogIndex - 1),
opacity : opacity
}).css(style);
if (!hasMask)
{
$("body").append(mask);
}
mask.fadeIn();
if (settings.maskClickClosed)
{
mask.css("cursor", "pointer").bind($.clickOrTouch(), this.proxy(function(){
this.close();
}));
}
else
{
mask.css("cursor", "default");
}
}
return this;
},
header : function(options) {
var settings = this.settings;
var target = this.target;
var type = this.type;
if (settings.type == "window" || settings.type == "iframe")
{
var _header = target.children('header');
var hasHeader = (_header.length > 0);
var title = (options.title || settings.title) || (_header.find("strong").text() || "");
var subTitle = options.subTitle;
var style = options.style;
var className = options.className;
var icon = options.icon;
var titleStyle = options.titleStyle;
if (hasHeader)
{
if (typeof options == "boolean" && !options)
{
_header.remove();
}
else
{
style = (typeof style == "undefined") ? (_header.attr('style') || "") : style;
className = (typeof className == "undefined") ? (_header.attr('class') || "") : className;
titleStyle = (typeof titleStyle == "undefined") ? (_header.children("strong").attr('style') || "") : titleStyle;
subTitle = (typeof subTitle == "undefined") ? (_header.find('small')[0].outerHTML || "") : subTitle;
icon = (typeof icon == "undefined") ? (_header.find(".fa")[0].outerHTML || "") : icon;
_header.attr({"style" : style, "class" : className});
_header.find('strong').attr("style", titleStyle).html(icon + title + subTitle);
}
}
else
{
style = style || "";
style = (style != "" ? ' style="'+style+'"' : "");
className = className || "";
className = (className != "" ? ' class="'+className+'"' : "");
titleStyle = titleStyle || "";
titleStyle = (titleStyle != "") ? ' style="'+titleStyle+'"' : "";
subTitle = subTitle || "";
icon = icon || "";
var headerHTML = '
';
if (target.children('section').length > 0)
{
target.children('section').before(headerHTML);
}
else
{
target.append(headerHTML);
}
}
target.trigger('dialog.reset');
}
return this;
},
content : function(options) {
var target = this.target;
var type = this.type;
var settings = this.settings;
var section = target.children('section');
var padding = options.padding;
var content = options.content;
var from = options.from || "";
var buttons = options.buttons || settings.buttons;
if (typeof options === "string") {
content = options;
}
if (type === "iframe") {
padding = 0;
}
if (type !== "iframe" && from !== "") {
content = $(from).html();
}
if (section.length > 0)
{
if (type !== "iframe")
{
padding = (typeof padding == "undefined") ? (section.css('padding') || 0) : padding;
content = (typeof content == "undefined") ? (section.html() || "") : content;
section.css("padding", padding).html(content);
}
else
{
section.children('iframe').attr('src', options.url || content);
}
}
else
{
if (type === "iframe")
{
padding = 0;
content = '
';
}
if (type === "prompt" || type === "prompt-app")
{
if(type === "prompt") {
padding = padding + "px " + padding + "px 0 "+padding;
}
content = '
'+settings.title+'
'+content+'
';
}
if (type === "loading")
{
if(content === "") {
content = '
loading....
';
}
}
if (type === "image")
{
var imageURL = content;
}
var buttonsClass = buttons['class'];
var html = '
';
if (type === "alert")
{
html += '
';
}
if (type === "alert-app")
{
html += '
';
}
if (type === "confirm")
{
html += '
';
}
if (type === "confirm-app")
{
html += '
';
}
if (type === "prompt")
{
html += '
';
}
if (type === "prompt-app")
{
html += '
';
}
target.append(html);
if(type === "image")
{
target.children('section').html('图片加载中...');
if(typeof imageURL === "object")
{
}
else
{
var image = new Image();
image.className = "pui-size-auto";
image.onload = function() {
target.children('section').html(image);
target.trigger('dialog.reset');
};
image.src = imageURL;
}
}
}
if(type === "iframe")
{
section = target.children('section');
var iframe = section.children('iframe');
this.proxy(this.onbeforeload)();
iframe[0].contentWindow.onload = iframe[0].contentWindow.onreadystatechange = this.proxy(this.onload);
}
if (type === "alert" || type === "alert-app" || type === "confirm" || type === "confirm-app") {
target.find('[button="yes"]').bind($.clickOrTouch(), this.proxy(function(){
this.proxy(this.yes || new Function)();
this.close();
}));
}
if (type === "prompt" || type === "prompt-app") {
target.find('[button="yes"]').bind($.clickOrTouch(), this.proxy(function(){
this.proxy(this.yes || new Function)();
}));
}
if (type === "confirm" || type === "confirm-app" || type === "prompt" || type === "prompt-app") {
target.find('[button="cancel"]').bind($.clickOrTouch(), this.proxy(function(){
this.proxy(this.cancel || new Function)();
this.close();
}));
}
target.trigger('dialog.reset');
return this;
},
footer : function(content) {
var settings = this.settings;
if (settings.type === "window" || settings.type === "iframe")
{
var target = this.target;
var _footer = target.children('footer');
if (_footer.length > 0)
{
if (typeof content === "boolean" && !content)
{
_footer.remove();
}
else
{
content = (typeof content === "undefined") ? (_footer.html() || "") : content;
_footer.html(content);
}
}
else
{
if(content !== "") target.append('
');
}
target.trigger('dialog.reset');
}
return this;
},
toolbar : function(options) {
var settings = this.settings;
var target = this.target;
var signleClose = target.children('.pui-close');
var hasSignleClose = (signleClose.length > 0);
if (typeof options === "boolean" && !options)
{
if (hasSignleClose) signleClose.remove();
}
if (typeof options === "string" && options === 'close')
{
if (signleClose.length < 1)
{
target.append(this.signleCloseBtn);
target.children('.pui-close').bind($.clickOrTouch(), this.proxy(function(){
this.close();
}));
}
}
if (settings.type === "window" || settings.type === "iframe")
{
var toolbar = target.children('.pui-dialog-toolbar');
var hasToolbar = (toolbar.length > 0);
if (typeof options === "boolean" && !options)
{
if(hasToolbar) toolbar.remove();
}
if (typeof options === "object")
{
if(hasSignleClose) signleClose.remove();
var list = options;
console.log(list);
var defaults = {
close : {
show : true,
title : "关闭"
},
min : {
show : false,
title : "最小化"
},
max : {
show : false,
title : "最大化"
},
blank : {
show : false,
title : "新窗口打开"
},
refresh: {
show : false,
title : "刷新窗口"
}
};
options = $.extend(defaults, options);
var _this = this;
var close = options.close;
var min = options.min;
var max = options.max;
var blank = options.blank;
var refresh = options.refresh;
if (hasToolbar)
{
if(!close) toolbar.find('.pui-dialog-close').remove();
if(!min) toolbar.find('.pui-dialog-min').remove();
if(!max) toolbar.find('.pui-dialog-max').remove();
if(!blank) toolbar.find('.pui-dialog-blank').remove();
if(!refresh) toolbar.find('.pui-dialog-refresh').remove();
}
else
{
toolbar = $('
');
target.append(toolbar);
for (var i in list)
{
var item = list[i];
if ( (typeof item == "boolean" && item) || item.show || typeof item == "function")
{
var btn = "";
switch (i) {
case "close" :
btn = '
';
break;
case "min" :
btn = '
';
break;
case "max" :
btn = '
';
break;
case "blank" :
btn = '
';
break;
case "refresh" :
btn = '
';
break;
}
toolbar.append(btn);
var callback = (typeof item == "function") ? this.proxy(item) : new Function;
target.find('.pui-dialog-' + i).bind($.clickOrTouch(), function() {
var type = $(this).attr('type');
//console.log("toolbar.type=>", type);
_this[type](callback);
});
}
}
}
}
}
target.trigger('dialog.reset');
return this;
},
width : function(width) {
var target = this.target;
width = (typeof width == "number") ? width + "px" : width;
if(typeof this._width == "undefined") this._width = width;
if(typeof width == "string" && width.indexOf("%") > 0) {
width = $(window).width() * (parseFloat(width) / 100);
}
target.width(width);
target.trigger('dialog.reset');
return this;
},
height: function(height) {
var target = this.target;
height = (typeof height == "number") ? height + "px" : height;
if(typeof this._height == "undefined") this._height = height;
if(typeof height == "string" && height.indexOf("%") > 0) {
height = $(window).height() * (parseFloat(height) / 100);
}
target.height(height);
target.trigger('dialog.reset');
return this;
},
resize : function(width, height) {
this.width(width);
this.height(height);
return this;
},
reset : function(callback) {
var target = this.target;
var type = this.type;
var section = target.children('section'), height;
if(type == "iframe" || type == "window")
{
height = target.height() - target.children('header').outerHeight() - target.children('footer').outerHeight();
section.height(height);
}
this.position({
top : this.settings.top,
left : this.settings.left
});
this.proxy(callback || this.onreset)();
},
min : function(callback) {
this.status = "min";
this.proxy(callback || this.onmin)();
return this;
},
max : function(callback) {
this.status = "max";
this.resize("100%", "100%");
this.position({top:0, left:0});
this.proxy(callback || this.onmax)();
return this;
},
blank : function(callback) {
this.proxy(callback || this.onblank)();
return this;
},
refresh : function(callback) {
this.status = "refresh";
if(this.type == "iframe")
{
var target = this.target;
var section = target.children('section');
var iframe = section.children('iframe');
this.proxy(this.onbeforeload)();
iframe[0].contentWindow.onload = iframe[0].contentWindow.onreadystatechange = this.proxy(this.onload);
iframe[0].contentWindow.location.reload();
this.proxy(callback || this.onrefresh)();
}
return this;
},
css : function(cssText) {
this.target.css(cssText);
return this;
},
fixed : function(position) {
position = (typeof position == "boolean" && position) ? "fixed" : position;
this.css("position", position);
return this;
},
parentDialog : function(queryString) {
var target = this.target;
var dialogId = "";
queryString = queryString.slice(1, queryString.length).split("&");
for (var i=0, len = queryString.length; i < len; i ++)
{
var item = queryString[i].split('=');
if(item[0] == "_dialog") {
dialogId = item[1];
}
}
return dialog.get(dialogId);
},
position : function(options) {
var target = this.target;
var settings = this.settings;
var $window = $(window);
var top = options.top || "center";
var left = options.left || "center";
switch(top) {
case "top":
top = 0;
break;
case "bottom":
top = $window.height() - target.outerHeight();
break;
case "center":
top = ($window.height() - target.outerHeight()) / 2;
break;
default :
top = top;
break;
}
switch(left) {
case "left":
left = 0;
break;
case "right":
left = $window.width() - target.outerWidth();
break;
case "center":
left = ($window.width() - target.outerWidth()) / 2;
break;
default :
left = left;
break;
}
settings._top = top;
settings._left = left;
target.css({
top : top + "px",
left : left + "px"
});
return this;
},
zIndex : function(index) {
this.target.css('z-index', index);
return this;
},
on : function(event, callback) {
},
show : function(callback) {
this.status = "show";
var target = this.target;
var settings = this.settings;
var mask = $("#" + this.id + '-mask');
var hasMask = (mask.length > 0);
this.position({
top : settings.top,
left : settings.left
});
this.lockScreen(settings.lockScreen);
//console.log("settings._top=>",settings._top);
if(target.length > 0)
{
if(hasMask) mask.fadeIn();
if(settings.animated)
{
//console.log('target.css.top', target.css('top'));
target.css({
top : "-"+ $(window).height() + "px"
}).stop().animate({
top : settings._top + "px",
opacity : "show"
}, settings.speed);
}
else
{
target.fadeIn();
this.proxy(callback || this.onshow)();
}
}
return this;
},
hide : function(callback) {
this.close(callback);
return this;
},
close : function(callback) {
this.status = "close";
var $this = this;
var target = this.target;
var settings = this.settings;
var mask = $("#" + this.id + '-mask');
var hasMask = (mask.length > 0);
if(!settings.cache) {
if(hasMask)
{
mask.fadeOut(function(){
mask.remove();
});
}
if(!settings.animated)
{
this.remove(callback);
}
else
{
target.stop().animate({
top : $(window).height() * 2 + "px",
opacity : "hide"
}, settings.speed, $.proxy(function(){
$this.remove(callback);
}));
}
}
else
{
if(hasMask) mask.fadeOut();
if(!settings.animated)
{
target.fadeOut();
this.proxy(callback || this.onclose)();
}
else
{
callback = this.proxy(callback || this.onclose);
target.stop().animate({
top : $(window).height() * 2 + "px",
opacity : "hide"
}, settings.speed, $.proxy(function() {
callback();
}));
}
}
this.lockScreen(false);
return this;
},
remove : function(callback) {
this.status = "remove";
this.target.remove();
this.proxy(callback || this.onremove)();
return this;
},
buttons : function() {
return this;
},
loading : function() {
return this;
},
mediaQuery : function(queries) {
queries = queries || [];
},
timeout : function(options) {
if(typeof options == "boolean" && !arguments[0]) return this;
var _this = this;
var time = (typeof options == "boolean" && options) ? 3000 : (options[0] || 3000);
time = (typeof options == "number") ? options : time;
var callback = (typeof options == "function") ? options : options[1];
callback = callback || new Function;
var timer = setTimeout(function() {
clearTimeout(timer);
_this.close(callback);
}, time);
return this;
}
};
dialog.list = [];
dialog.get = function(id) {
return this.list[id];
};
$.dialog = dialog;
})(PlaneUI);
(function($) {
$.draggableIndex = 1000;
$.fn.draggable = function(options) {
options = options || {};
var defaults = {
target : null,
container : null,
touch : true,
x : true, // horizontal drag
y : true // vertical drag
};
var settings = $.extend(defaults, options);
var posX, posY;
var body = $("body");
var classPrefix = "pui-";
$(this).each(function() {
var $this = $(this);
var target = settings.target;
if (!target) {
target = $this;
}
target.css("cursor", "move").bind($.mouseOrTouch("mousedown", "touchstart"), function(e) {
e = e || window.event; //IE
posX = e.clientX - parseInt($this.position().left);
posY = e.clientY - parseInt($this.position().top);
if (!settings.target) {
$.draggableIndex ++;
target.css("z-index", $.draggableIndex);
}
document.onmousemove = moveAction;
});
if (settings.touch) {
target.touchDraggable(settings);
}
var userCanSelect = function (obj) {
obj.removeClass(classPrefix + "user-unselect").off("selectstart");
};
var userUnselect = function (obj) {
// selectstart for IE
obj.addClass(classPrefix + "user-unselect").on("selectstart", function(event) {
return false;
});
};
var moveAction = function (e) {
e = e || window.event; //IE
var left, top, nowLeft = parseInt($this.position().left), nowTop = parseInt($this.position().top);
var parentWidth = (settings.container) ? settings.container.width() : $(window).width();
if ( nowLeft >= 0 )
{
if ( nowLeft + $this.width() <= parentWidth)
{
left = e.clientX - posX;
}
else
{
left = parentWidth - $this.width();
document.onmousemove = null;
}
}
else
{
left = 0;
document.onmousemove = null;
}
if ( nowTop >= 0 )
{
if (settings.container)
{
var parentHeight = settings.container.height();
if ( nowTop + $this.outerHeight() <= parentHeight)
{
top = e.clientY - posY;
}
else
{
top = parentHeight - $this.outerHeight();
document.onmousemove = null;
}
}
else
{
top = e.clientY - posY;
}
}
else
{
top = 0;
document.onmousemove = null;
}
document.onselectstart = function() {
return false;
};
userUnselect(body);
userUnselect($this);
if (settings.x) $this[0].style.left = left + "px";
if (settings.y) $this[0].style.top = top + "px";
};
document.onmouseup = function() {
userCanSelect(body);
userCanSelect($this);
document.onselectstart = null;
document.onmousemove = null;
};
});
};
})(PlaneUI);
(function($) {
$.fn.touchDraggable = function(options) {
options = options || {};
var defaults = {
container : null,
parent : false,
x : true,
y : true
};
var settings = $.extend(defaults, options);
$(this).each(function() {
var offset = null;
var start = function(e) {
var orig = e.originalEvent;
var parent = (settings.parent) ? $(this).parent() : $(this);
var pos = parent.position();
if (settings.parent) {
$.dialogIndex ++;
parent.css("zIndex", $.dialogIndex);
}
offset = {
x : orig.changedTouches[0].pageX - pos.left,
y : orig.changedTouches[0].pageY - pos.top
};
$(this).bind("touchmove", moveAction);
};
var moveAction = function(e) {
e.preventDefault();
var orig = e.originalEvent, top, left;
var target = (settings.parent) ? $(this).parent() : $(this);
var nowLeft = parseInt(target.position().left);
var nowTop = parseInt(target.position().top);
var parentWidth = (settings.container) ? settings.container.width() : $(window).width();
if (nowLeft >= 0)
{
if ( nowLeft + target.width() <= parentWidth)
{
left = orig.changedTouches[0].pageX - offset.x;
}
else
{
left = parentWidth - target.width();
$(this).unbind("touchmove", moveAction);
}
}
else
{
left = 0;
$(this).unbind("touchmove", moveAction);
}
if ( nowTop >= 0 )
{
if (settings.container)
{
var parentHeight = settings.container.height();
if ( nowTop + target.outerHeight() <= parentHeight)
{
top = orig.changedTouches[0].pageY - offset.y;
}
else
{
top = parentHeight - target.outerHeight();
$(this).unbind("touchmove", moveAction);
}
}
else
{
top = orig.changedTouches[0].pageY - offset.y;
}
}
else
{
top = 0;
$(this).unbind("touchmove", moveAction);
}
if (settings.x) {
target.css("left", left);
}
if (settings.y) {
target.css("top", top);
}
};
$(this).bind("touchstart", start);
});
};
})(PlaneUI);
(function($) {
$.fn.fileInput = function(onchange) {
$(this.selector ? this.selector : ".pui-file-input").each(function() {
var $this = $(this);
var fileInput = $this.find("input[type=\"file\"]");
var btn = $this.find(".pui-file-input-btn");
fileInput.bind("change", function() {
$.proxy(onchange || function() {}, this)();
});
btn.bind("click", function() {
fileInput.trigger("click");
});
});
};
})(PlaneUI);
(function($) {
$(function(){
$(".pui-font-sizer > span").bind($.clickOrTouch(), function() {
var $this = $(this);
var target = $(this).parent().attr("target");
$this.each(function(){
var size = $(this).attr("size");
if(size == "default") {
$(target).removeAttr("style");
} else {
$(target).css({
fontSize : size
});
}
});
});
});
})(PUI);
(function ($) {
$.formValidatorImageFormats = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
$.formValidatorRules = {
username : /^[a-zA-Z]\w{4,15}$/,
password : /^[a-zA-Z][a-zA-Z0-9\.\-\_]{5,15}$/,
enName : /^[a-zA-Z]{2,}$/,
uppercase : /^[A-Z]+$/,
lowercase : /^[a-z]+$/,
chinese : /^[\u4e00-\u9fa5]+$/,
email : /^[0-9a-z][_.0-9a-z-]{0,31}@([0-9a-z][0-9a-z-]{0,30}[0-9a-z]\.){1,3}[a-z]{2,4}$/,
tel : /^\d{3}-\d{8}|\d{4}-\d{7,8}$/,
telExt : /^\d{3}-\d{8}|\d{4}-\d{7,8}-?\d+?$/,
mobile : /^1(30|31|32|33|34|35|36|37|38|39|45|47|50|51|52|53|55|56|57|58|59|76|77|78|80|81|82|83|84|85|86|87|88|89)\d{8}$/,
mobileI18n : /^(\+86)1(30|31|32|33|34|35|36|37|38|39|45|47|50|51|52|53|55|56|57|58|59|76|77|78|80|81|82|83|84|85|86|87|88|89)\d{8}$/,
zipcode : /^[1-9]\d{5}$/,
qq : /^[1-9]\\d{4,10}$/,
domain : /^([a-zA-Z0-9\-]+)\.([a-zA-Z0-9\-]+)\.(com|net|cn|jp|tw|hk|edu|biz|gov|org|info|asia|mobi|co|cc|tt|me|tv|name|de)\.?(cn|hk|tw|jp)?$/,
url : /^(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?$/,
ipv4 : /^((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))))$/,
idcard : /^\d{17}([0-9]|X)$/,
idcard1518 : /(^\d{15}$)|(^\d{17}([0-9]|X)$)/,
integer : /^\d+$/, // 0+,正整数
number : function(value) {
return !isNaN(value);
},
image : function(value){
return ($.inArray(value, $.formValidatorImageFormats) >= 0);
}
};
$.formValidatorRules.fax = $.formValidatorRules.telExt;
$.formValidatorRules.confirmPassword = $.formValidatorRules.password;
$.formValidatorIcons = {
error : '
',
success : '
'
};
$.formValidatorRuleMessages = {
username : {
normal : '* 用户名必须以英文字母开头的英文字母、数字或下划线的5-16位组合。',
empty : $.formValidatorIcons.error + ' 错误:用户名不能为空。',
error : $.formValidatorIcons.error + ' 错误:用户名必须以英文字母开头的英文字母、数字或下划线的5-16位组合。',
},
password : {
normal : '* 密码由5-16位以英文字母开头的英文字母、数字、小数点、横线或下划线的组成。',
empty : $.formValidatorIcons.error + ' 错误:密码不能为空。',
error : $.formValidatorIcons.error + ' 错误:密码由5-16位以英文字母开头的英文字母、数字、小数点、横线或下划线的组成。',
},
confirmPassword : {
normal : "* 再次填写刚刚输入的密码,以便确认密码。",
empty : $.formValidatorIcons.error + ' 错误:确认密码不能为空。',
error : $.formValidatorIcons.error + ' 错误:两次输入的密码不一致或密码不正确。'
},
enName : {
normal : "* 请填写英文名字。",
empty : $.formValidatorIcons.error + ' 错误:英文名字不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的英文名字。'
},
uppercase : {
normal : "* 请填写大写的英文字母。",
error : $.formValidatorIcons.error + ' 错误:请填写大写的英文字母。'
},
lowercase : {
normal : "* 请填写小写的英文字母。",
error : $.formValidatorIcons.error + ' 错误:请填写小写的英文字母。'
},
chinese : {
normal : "* 请填写中文字符。",
error : $.formValidatorIcons.error + ' 错误:只能填写中文字符。'
},
email : {
normal : "* 请填写邮箱地址。",
empty : $.formValidatorIcons.error + ' 错误:邮箱地址不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的邮箱地址。'
},
tel : {
normal : "* 格式:区号-固定电话号码。",
empty : $.formValidatorIcons.error + ' 错误:固定电话号码不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的固定电话号码。'
},
telExt : {
normal : "* 格式:区号-固定电话号码、区号-固定电话号码-分机号。",
empty : $.formValidatorIcons.error + ' 错误:固定电话号码不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的固定电话号码。'
},
fax : {
normal : "* 格式:区号-固定电话号码、区号-固定电话号码-分机号。",
empty : $.formValidatorIcons.error + ' 错误:传真号码不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的传真号码。'
},
moblie : {
empty : $.formValidatorIcons.error + ' 错误:手机号码不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的手机号码。'
},
moblieI18n : {
normal : '* 格式:+86手机号码',
empty : $.formValidatorIcons.error + ' 错误:手机号码不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的手机号码,格式:+86手机号码。'
},
zipcode : {
empty : $.formValidatorIcons.error + ' 错误:邮政编码不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的邮政编码。'
},
qq : {
empty : $.formValidatorIcons.error + ' 错误:QQ号码不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的QQ号码(5-10位数字)。'
},
domain : {
normal : '* 格式:www.xxx.com | xxx.xxx.com 。',
empty : $.formValidatorIcons.error + ' 错误:域名不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的域名。'
},
url : {
normal : '* (http|https|ftp)://www.xxx.com/xxx/xxx.html?xxx',
empty : $.formValidatorIcons.error + ' 错误:URL(网址)不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的URL(网址)。'
},
ipv4 : {
normal : '* IPv4地址:0~255.0~255.0~255.0~255',
empty : $.formValidatorIcons.error + ' 错误:IP地址不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的IP地址。'
},
idcard : {
normal : '* 填写18位的身份证号码',
empty : $.formValidatorIcons.error + ' 错误:身份证号码不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的身份证号码。'
},
idcard1518 : {
normal : '* 填写15或18位的身份证号码',
empty : $.formValidatorIcons.error + ' 错误:身份证号码不能为空。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的身份证号码(15或18位)。'
},
integer : {
normal : '* 只能填写正整数(0及以上)。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的正整数(0及以上)。'
},
number : {
normal : '* 只能填写数字值。',
error : $.formValidatorIcons.error + ' 错误:请填写正确的数字值。'
},
image : {
normal : '* 只能上传 '+$.formValidatorImageFormats.join(', ')+' 格式的图片文件。',
error : $.formValidatorIcons.error + ' 错误:只能上传 '+$.formValidatorImageFormats.join(', ')+' 格式的图片文件。',
}
};
var isUndefined = function(obj) {
return (typeof obj == "undefined");
};
$.fn.formValidator = function(options, ajaxSubmit, _messages) {
ajaxSubmit = ajaxSubmit || false;
var submitBtn = $(this);
var form = submitBtn.parent("form");
var validator = function(_this) {
var name = _this.attr('name');
var value = _this.val();
var option = options[name];
var empty = option.empty || false;
var element = form.find('[name="'+name+'"]');
var role = form.find('[fv-role="'+name+'"]');
var msgNormal = role.find('[type="normal"]');
var msgEmpty = role.find('[type="empty"]');
var msgSuccess = role.find('[type="success"]');
var msgError = role.find('[type="error"]');
var equalTo = form.find('[name="'+option.equalTo+'"]');
var checked = 0;
var isSuccess = false;
if( !isUndefined(option.checked) ) checked = form.find('[name="'+name+'"]:checked').length;
var exp = {
min : ( !isUndefined(option.min) && parseFloat(value) < option.min),
max : ( !isUndefined(option.max) && parseFloat(value) > option.max),
minLength : ( !isUndefined(option.minLength) && value.length < option.minLength),
maxLength : ( !isUndefined(option.maxLength) && value.length > option.maxLength),
checkedEmpty : ( !isUndefined(option.checked) && checked == 0),
checked : ( !isUndefined(option.checked) && typeof option.checked == "number" && checked < option.checked),
checkedMin : ( !isUndefined(option.checked) && typeof option.checked == "object" && checked < option.checked[0]),
checkedMax : ( !isUndefined(option.checked) && typeof option.checked == "object" && checked > option.checked[1]),
equalTo : ( !isUndefined(option.equalTo) && value !== equalTo.val())
};
var successHandler = function(){
_this.removeClass("fv-error").addClass("fv-success");
role.find('span').hide();
msgSuccess.show();
isSuccess = true;
};
var errorHandler = function(){
_this.removeClass("fv-success").addClass("fv-error");
role.find('span').hide();
msgError.fadeIn();
isSuccess = false;
};
if(!empty)
{
if (value == "" || exp.checkedEmpty)
{
_this.removeClass("fv-success").addClass("fv-error");
role.find('span').hide();
msgEmpty.show();
}
else if (exp.min || exp.max || exp.minLength || exp.maxLength || exp.equalTo || exp.checked || exp.checkedMin || exp.checkedMax)
{
errorHandler();
}
else if (!isUndefined(option.ajax))
{
$.ajax({
type : "get",
async : false,
dataType : (option.jsonp ? "jsonp" : "json" ) || "json",
url : option.ajax + "&" + name + "=" + value,
success : function(json) {
if(json.status == 1) successHandler();
else errorHandler();
//console.log(json);
}
});
}
else if (!isUndefined(option.rule))
{
var rule = option.rule;
var fileExt = value.split('.');
var ruleExp = (typeof rule == "function") ? rule : $.formValidatorRules[rule];
fileExt = fileExt[fileExt.length - 1];
if(typeof ruleExp == "function") {
if(ruleExp(rule == "image" ? fileExt : value)) successHandler();
else errorHandler();
}
else if(typeof ruleExp == "object")
{
if(ruleExp.test(value)) successHandler();
else errorHandler();
}
else
{
}
console.log(typeof ruleExp, ruleExp);
}
else
{
if(!isUndefined(option.min) || !isUndefined(option.max)) _this.val(parseFloat(value) || 0);
successHandler();
}
}
else
{
if(value !== "")
{
}
}
//$.proxy(option.success || new Function, element)();
//$.proxy(option.error || new Function, element)();
//console.log('isSuccess=>', isSuccess);
return isSuccess;
};
for (var i in options)
{
var defaultMessages = {
normal : '* 必填项',
empty : $.formValidatorIcons.error + ' 错误:不能为空。',
error : $.formValidatorIcons.error + ' 错误:请正确填写。',
success : $.formValidatorIcons.success + ' 正确'
};
var element = form.find('[name="'+i+'"]');
var role = form.find('[fv-role="'+i+'"]');
var option = options[i];
var type = element.attr('type'), message;
var ruleMessages = $.formValidatorRuleMessages;
if(isUndefined(option.message) && ruleMessages[option.rule]) option.message = "rule";
if(!isUndefined(option.message) && !isUndefined(option.rule) && option.message == "rule")
{
message = $.extend(defaultMessages, ruleMessages[option.rule] || {});
}
else
{
message = $.extend(defaultMessages, _messages);
message = $.extend(message, option.message);
}
//console.log('option=>', option, i, "message =>", message);
for (var x in message)
{
if(typeof option == "boolean" && x == "error") break;
role.append('
'+message[x]+' ');
}
//console.log("$(this).length", element.length);
element.bind((type == "file" || element[0].tagName == "SELECT") ? "change" : "blur", function(event) {
validator($(this));
});
}
submitBtn.bind($.clickOrTouch() || "click", function() {
var errors = 0;
for (var i in options)
{
var element = form.find('[name="'+i+'"]');
if(!validator(element)) errors++;
}
console.log("errors =>", errors);
if (errors > 0) return false;
else
{
if (typeof ajaxSubmit == "object")
{
$.ajax($.extend({
type : "post",
data : form.serializeArray()
}, ajaxSubmit));
return false;
}
else
{
form.submit();
}
}
});
return this;
};
})(PlaneUI);
(function($) {
$.fn.hoverScroller = function(options) {
options = options || {};
var defaults = {
target : "img",
scrollType : "marginTop", // transform
speed : 600
};
var settings = $.extend(defaults, options);
$(this).each(function() {
var timer;
var $this = $(this);
var target = $(this).find(settings.target);
function scrollTop() {
var speed = 0;
var targetHeight = parseInt(target.height());
$(this).css("cursor", "pointer");
timer = setInterval(function() {
speed += Math.floor(targetHeight / 200);
target.css({marginTop : "-" + speed + "px"});
var nowTop = parseInt(target.css("marginTop"));
if (-nowTop >= targetHeight - $this.height())
{
target.css({marginTop : "-" + (targetHeight - $this.height()) + "px)"});
clearInterval(timer);
}
}, settings.speed / 10);
}
function scrollDown() {
$(this).css("cursor", "");
clearInterval(timer);
target.animate({marginTop : 0}, settings.speed);
}
$this.css("overflow", "hidden").hover(scrollTop, scrollDown);
});
};
})(PlaneUI);
(function($) {
// 在可视窗口的上面
$.inScreenAbove = function(element, threshold) {
var top = $(window).scrollTop(), $el = $(element);
if ($el.length < 1) {
throw new TypeError("$.inScreenAbove(): element don't exist.");
}
return (top >= $el.offset().top + $el.height() - (threshold || 0));
};
// 在可视窗口的下面
$.inScreenBelow = function(element, threshold) {
var $window = $(window), $el = $(element);
if ($el.length < 1) {
throw new TypeError("$.inScreenBelow(): element don't exist.");
}
return ($window.height() + $window.scrollTop() <= $el.offset().top - (threshold || 0));
};
$.inScreenLeft = function(element, threshold) {
var left = $(window).scrollLeft(), $el = $(element);
if ($el.length < 1) {
throw new TypeError("$.inScreenLeft(): element don't exist.");
}
return (left >= $el.offset().left + $el.width() - (threshold || 0));
};
$.inScreenRight = function(element, threshold) {
var $window = $(window), $el = $(element);
if ($el.length < 1) {
throw new TypeError("$.inScreenRight(): element don't exist.");
}
return ($window.width() + $window.scrollLeft() <= $el.offset().left - (threshold || 0));
};
$.inViewport = function(element, threshold) {
if ($(element).length < 1) {
throw new TypeError("$.inViewport(): element don't exist.");
}
return (!$.inScreenLeft(element, threshold) &&
!$.inScreenRight(element, threshold) &&
!$.inScreenAbove(element, threshold) &&
!$.inScreenBelow(element, threshold));
};
$.extend($.expr[':'], {
"in-screen-below": function(el) {
return $.inScreenBelow(el);
},
"in-screen-above": function(el) {
return $.inScreenAbove(el);
},
"in-screen-left": function(el) {
return $.inScreenLeft(el);
},
"in-screen-right": function(el) {
return $.inScreenRight(el);
},
"in-viewport": function(el) {
return $.inViewport(el);
}
});
})(PlaneUI);
(function($) {
$(function() {
var subMenuClass = ".pui-sub-menu";
$(".pui-menu-accordion.click-toggle > li > a").bind($.clickOrTouch(), function() {
$(this).parent().toggleClass("submenu-open").children(subMenuClass).slideToggle();
});
$(".pui-menu-accordion.click > li > a").bind($.clickOrTouch(), function() {
var li = $(this).parent();
if (!li.hasClass("submenu-open")) {
li.parent().find("li").removeClass("submenu-open").find(subMenuClass).slideUp();
li.toggleClass("submenu-open").children(subMenuClass).slideDown();
}
});
});
})(PUI);
(function ($) {
$.menuDropdown = function(options) {
var defaults = {
bind : "click",
target : "menu-dropdown-target",
direction : "default", // bottom-left
hasArrow : false,
contextMenuTarget : "show-context-menu",
callback : new Function
};
var settings = $.extend(defaults, options);
$("["+settings.contextMenuTarget+"]").bind($.contextMenuOrTouch(), function(event){
event = event || window.event;
var $this = $(this);
var target = $this.attr(settings.contextMenuTarget);
var targetObj = $(target);
var pageX = event.pageX;
var pageY = event.pageY;
if(event.type == "touchend") {
pageX = $this.offset().left;
pageY = $this.offset().top + $this.outerHeight();
}
targetObj.show().css({
top : pageY,
left : pageX
});
$(document).bind($.clickOrTouch(), function(){
targetObj.hide();
});
targetObj.mouseleave(function(){
targetObj.hide();
});
return false;
});
$("["+settings.target+"]").bind($.clickOrTouch(), function() {
var $this = $(this);
var target = $this.attr(settings.target);
var targetObj = $(target);
var direction = $this.attr("menu-dropdown-direction");
if(typeof(direction) == 'undefined' || direction == "") {
direction = settings.direction;
}
$this.find(".pui-btn").addClass("active");
targetObj.show();
switch(direction)
{
case "left-top":
targetObj.css({
top : $this.offset().top,
left : $this.offset().left - targetObj.outerWidth() - 4
});
break;
case "left-bottom":
targetObj.css({
top : $this.offset().top - targetObj.outerHeight() + $this.outerHeight(),
left : $this.offset().left - targetObj.outerWidth() - 4
});
break;
case "right-top":
targetObj.css({
top : $this.offset().top,
left : $this.offset().left + $this.outerWidth() + 4
});
break;
case "right-bottom":
targetObj.css({
top : $this.offset().top - targetObj.outerHeight() + $this.outerHeight(),
left : $this.offset().left + $this.outerWidth() + 4
});
break;
case "top-left":
targetObj.css({
top : $this.offset().top - 2 - (settings.hasArrow ? 8 : 0) - targetObj.outerHeight(),
left : $this.offset().left
});
break;
case "top-right":
targetObj.css({
top : $this.offset().top - 2 - (settings.hasArrow ? 8 : 0) - targetObj.outerHeight(),
left : $this.offset().left + $this.outerWidth() - targetObj.outerWidth()
});
break;
case "bottom-right":
targetObj.css({
top : $this.offset().top + $this.outerHeight() + 2 + (settings.hasArrow ? 8 : 0),
left : $this.offset().left + $this.outerWidth() - targetObj.outerWidth()
});
break;
case "bottom-left":
default:
targetObj.css({
top : $this.offset().top + $this.outerHeight() + 2 + (settings.hasArrow ? 8 : 0),
left : $this.offset().left
});
break;
}
$(document).bind($.clickOrTouch(), function() {
targetObj.hide();
$this.find(".pui-btn").removeClass("active");
});
return false;
});
};
$(function(){
$(".pui-menu > li").bind("touchend", function() {
$(this).children(".pui-menu-dropdown").show().mouseleave(function() {
$(this).hide();
});
});
$.menuDropdown();
});
})(PlaneUI);
(function ($) {
$(function() {
$(".pui-notice").each(function() {
var timeout = $(this).attr("notice-timeout");
var closeBtn = $(this).find(".pui-close");
if(typeof timeout !== "undefined") {
timeout = parseInt(timeout);
var timer = setTimeout(function(){
closeBtn.trigger($.clickOrTouch());
clearTimeout(timer);
}, timeout);
}
closeBtn.bind($.clickOrTouch(), function() {
$(this).parent().css({minHeight: 0}).slideUp(500, function() {
$(this).remove();
});
});
});
});
})(PlaneUI);
(function ($) {
var drawed = false;
$.fn.extend({
ringProgress : function(options) {
options = options || {};
var defaults = {
redraw : false,
sector : false,
ringColor : '#30C4E9',
ringWidth : 6,
bgColor : '#fff',
textColor : '#666',
textFontSize : '16px',
textFontFamily : 'Arial',
textAlign : 'center',
textBaseline : 'middle',
zero : false
};
// 设置优先级:HTML属性设置 > jQuery插件设置 > 默认值
var settings = $.extend(defaults, options);
var _this = this;
this.settings = settings;
this.test = function(){alert('test')};
this.each(function(i) {
var $this = $(this);
var canvas = this;
var text = $this.text();
var progress = parseInt(text);
var context = canvas.getContext('2d');
var width = canvas.width;
var height = canvas.height;
if(window.devicePixelRatio > 1 && settings.redraw) {
width /= 2;
height /= 2;
}
var radius = width / 2;
if(settings.zero) {
progress = 1;
text = "0%";
}
var sector = $this.attr('sector');
var ringColor = $this.attr('ring-color');
var ringWidth = $this.attr('ring-width');
var bgColor = $this.attr('bg-color');
var textColor = $this.attr('text-color');
var textFontSize = $this.attr('text-font-size');
var textFontFamily = $this.attr('text-font-family');
var textAlign = $this.attr('text-align');
var textBaseline = $this.attr('text-baseline');
if (typeof(sector) == 'undefined' || sector == '') {
this.sector = sector = settings.sector;
}
if (typeof(ringColor) == 'undefined' || ringColor == '') {
this.ringColor = ringColor = settings.ringColor;
}
if (typeof(ringWidth) == 'undefined' || ringWidth == '') {
this.ringWidth = ringWidth = settings.ringWidth;
}
if (typeof(bgColor) == 'undefined' || bgColor == '') {
this.bgColor = bgColor = settings.bgColor;
}
if (typeof(textColor) == 'undefined' || textColor == '') {
this.textColor = textColor = settings.textColor;
}
if (typeof(textFontSize) == 'undefined' || textFontSize == '') {
this.textFontSize = textFontSize = settings.textFontSize;
}
if (typeof(textFontFamily) == 'undefined' || textFontFamily == '') {
this.textFontFamily = textFontFamily = settings.textFontFamily;
}
if (typeof(textAlign) == 'undefined' || textAlign == '') {
this.textAlign = textAlign = settings.textAlign;
}
if (typeof(textBaseline) == 'undefined' || textBaseline == '') {
this.textBaseline = textBaseline = settings.textBaseline;
}
if(progress >= 100) {
progress = 99.9999;
}
else if(progress < 1) {
progress = 1;
}
//console.log(width, height, bgColor, ringColor);
(function (canvas, context) {
if(settings.redraw) {
return ;
}
var devicePixelRatio = window.devicePixelRatio || 1;
var backingStorePixelRatio = context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1;
var ratio = devicePixelRatio / backingStorePixelRatio;
if (ratio > 1) {
canvas.style.height = canvas.height + 'px';
canvas.style.width = canvas.width + 'px';
canvas.width *= ratio;
canvas.height *= ratio;
context.scale(ratio, ratio);
}
})(canvas, context);
//console.log(window.devicePixelRatio+', '+canvas.width +', '+ canvas.height+', '+width+', '+height);
// 画底圆
context.clearRect(0, 0, width, height);
context.beginPath();
context.moveTo(width / 2, height / 2);
context.arc(width / 2, height / 2, radius, 0, Math.PI * 2, false);
context.closePath();
context.fillStyle = bgColor;
context.fill();
// 直接画圆环
//context.strokeStyle="#333";
//context.lineWidth= 5; // 线宽
//context.arc(width / 2, height / 2, radius - (5/2) , 0, Math.PI * 2, false);
//context.stroke();
// 画扇形(进度)
context.beginPath();
context.moveTo(width / 2, height / 2);
//整个圆为2PI,360 -> 1.5PI, 90 -> 0PI, 180 -> 0.5PI, 270 -> 1PI
// arc(x,y, 半径, 开始角度,结束角度, 顺时或逆时针)
var endAngle = Math.PI * (2 * (progress / 100)) - (Math.PI * 0.5);
context.arc(width / 2, height / 2, radius, Math.PI * 1.5, endAngle, false);
context.closePath();
context.fillStyle = ringColor;
context.fill();
// 画内部空白
if(sector === 'false' || !sector) {
context.beginPath();
context.moveTo(width / 2, height / 2);
context.arc(width / 2, height / 2, radius - ringWidth, 0, Math.PI * 2, true);
context.closePath();
context.fillStyle = '#fff';
context.fill();
}
// 文字
context.font = textFontSize + " " +textFontFamily;
context.fillStyle = textColor;
context.textAlign = textAlign;
context.textBaseline = textBaseline;
context.moveTo(width / 2, height / 2);
context.fillText(text, width / 2, height / 2);
});
return this;
},
ringProgressAnimation : function(options, options2) {
var defaults = {
start : 0,
end : 100,
speed : 1000
};
var defaults2 = {
redraw : true
};
var settings = $.extend(defaults, options);
var settings2 = $.extend(defaults2, options2);
var _this = this;
var timer = setInterval(function() {
settings.start ++;
$(_this).html(settings.start + "%").ringProgress(settings2);
if(settings.start >= settings.end) clearInterval(timer);
}, settings.speed);
return this;
}
});
})(PlaneUI);
(function ($) {
$(function(){
$("pui-radio").each(function(i) {
var $this = $(this);
var radio = $('
');
radio.attr("name", $this.attr('name'));
radio.val($this.attr('value'));
if($this.hasClass('checked')) {
radio.attr("checked", "checked");
}
if($this.attr('disabled') == "disabled") {
radio.attr("disabled", "disabled");
}
$this.append(radio);
$this.bind($.clickOrTouch(), function() {
if($(this).attr('disabled') == "disabled") return ;
var input = $(this).find('input');
if(input.attr('checked') == "checked") return ;
var name = $(this).attr('name');
$('input[name="'+name+'"]').removeAttr('checked');
$(this).addClass('checked').siblings().removeClass('checked');
input[0].checked = true;
});
});
});
})(PlaneUI);
(function ($) {
$.fn.rating = function(options) {
var defaults = {
score : 0,
total : 5,
titles : "非常差,很差,好,很好,非常好",
showTotal : true,
showScore : true,
ajaxURL : "",
clickHandler : null,
clickCallback : new Function
};
var settings = $.extend(defaults, options);
$(this).each(function() {
var $this = $(this);
var score = function(){
return (typeof($this.attr('score')) == "undefined") ? settings.score : $this.attr('score');
};
var floor = Math.floor(score());
var ceil = Math.ceil(score());
var total = $this.attr('total');
var titles = $this.attr('titles');
var showTotal = $this.attr('show-total');
var showScore = $this.attr('show-score');
var ajaxURL = $this.attr('ajax-url');
var clickCallback = $this.attr('click-callback');
total = (typeof(total) == "undefined") ? settings.total : parseInt(total);
titles = (typeof(titles) == "undefined") ? settings.titles.split(",") : titles.split(",");
if(typeof(showTotal) == "undefined") showTotal = settings.showTotal;
if(typeof(showScore) == "undefined") showScore = settings.showScore;
if(typeof(ajaxURL) == "undefined") ajaxURL = settings.ajaxURL;
if(typeof(clickCallback) == "undefined" || clickCallback == "")
{
clickCallback = settings.clickCallback;
}
else
{
clickCallback = window[clickCallback];
}
console.log(total, titles, showTotal, showScore, clickCallback);
for (var i = 1, length = total + 1; i < length; i++)
{
var className = '';
if (i <= floor)
{
className = ' class="full"';
}
else if (i > score() && i == ceil)
{
className = ' class="half"';
}
else if (i > ceil || score() == 0)
{
className = '';
}
//console.log(i+", "+score()+", "+floor+", "+ceil+", "+total+"
");
var span = $('
');
$this.append(span);
}
if(showTotal || showTotal == "true")
{
$this.append('
总分:'+total+'分 ');
}
if(showScore || showScore == "true")
{
$this.append('
平均分:'+score()+'分 ');
}
$this.find("span").bind({
"mouseenter" : function(event) {
var index = $(this).index();
$this.find("span").each(function(i) {
$(this).removeClass();
if (i <= index) {
$(this).addClass('full');
}
//console.log(i, score(), floor, ceil, total, $(this).attr('class'));
});
},
"mouseleave" : function(event) {
var index = $(this).index();
$this.find("span").each(function(i) {
i = i + 1;
$(this).removeClass();
if (i <= Math.floor(score()))
{
$(this).addClass('full');
}
else if (i > score() && i == Math.ceil(score()))
{
$(this).addClass("half");
}
});
},
"click" : function() {
if(typeof(settings.clickHandler) == "function") {
settings.clickHandler($this);
return ;
}
if (ajaxURL == "") {
console.error("错误:URL不能为空,Rating评价组件默认通过Ajax执行点击操作。");
return ;
}
var index = $(this).index();
$.post(ajaxURL, {score : score(), newscore : (index + 1), total : total}, function(data) {
$this.attr("score", data).find("small").remove();
if(showTotal || showTotal == "true") {
$this.append('
总分:'+total+'分 ');
}
if(showScore || showScore == "true") {
$this.append('
平均分:'+data+'分 ');
}
$this.find("span").each(function(i) {
i = i + 1;
$(this).removeClass();
if (i <= Math.floor(data))
{
$(this).addClass('full');
}
else if (i > data && i == Math.ceil(data))
{
$(this).addClass("half");
}
});
clickCallback($this);
});
}
});
});
};
})(PlaneUI);
(function($) {
$.fn.scrollTo = function (options) {
options = options || {};
var defaults = {
speed : 800,
direction : "top",
top : null,
left : null,
targetHash : true,
hashEmpty : true,
callback : function() {},
scrollTarget : "html, body"
};
var settings = $.extend(defaults, (typeof options === "object") ? options : {});
if (typeof options === "function") {
settings.callback = options;
}
$(this.selector ? this.selector : "[scrollto]").bind($.clickOrTouch(), function() {
var scrollHandler = function($this, target) {
var direction = {};
if (settings.top === 0) {
settings.top = "0px";
}
if (settings.left === 0) {
settings.left = "0px";
}
if (!settings.top && !settings.left) {
if (settings.direction === "left") {
direction = { scrollLeft : target.offset().left };
} else {
direction = { scrollTop : target.offset().top };
}
}
if (settings.top) {
direction.scrollTop = settings.top;
}
if (settings.left) {
direction.scrollLeft = settings.left;
}
$(settings.scrollTarget).animate(direction, settings.speed, function() {
if (settings.hashEmpty && window.addEventListener) { // IE9+
location.hash = "";
}
$.proxy(settings.callback, $this)(target);
});
};
if (settings.targetHash)
{
if (location.pathname.replace(/^\//, "") == this.pathname.replace(/^\//, "") && location.hostname == this.hostname)
{
var hash = this.hash;
var target = $(hash);
var $this = $(this);
target = target.length && target || $("[name=" + hash.slice(1) + "]");
if (target.length > 0)
{
scrollHandler($(this), target);
}
}
}
else
{
scrollHandler($(this), settings.scrollTarget);
}
return false;
});
};
})(PlaneUI);
(function ($) {
$(function() {
$(document).keyup(function(event) {
if (event.keyCode ==13) {
$(".pui-search-submit").trigger("click");
}
});
$('.pui-search-single-button').hover(function() {
var $this = $(this);
var hoverWidth = $this.attr('hover-width');
var keywordInput = $this.find('.pui-search-keywords');
$this.width(hoverWidth);
keywordInput.removeClass('pui-search-keywords-slide-reverse').addClass('pui-search-keywords-slide');
return false;
}, function() {
var $this = $(this);
var width = $this.attr('width');
var keywordInput = $this.find('.pui-search-keywords');
$this.width(width);
keywordInput.removeClass('pui-search-keywords-slide-reverse').addClass('pui-search-keywords-slide-reverse');
return false;
});
});
})(PlaneUI);
(function ($) {
$.fn.sidePosition = function(options) {
var defaults = {
zIndexTop : false,
attr : "pui-side-position",
showMode : "slide",
speed : 300,
mask : false,
maskFullOpacity : false
};
var settings = $.extend(defaults, options);
var selector = ($(this).selector === "") ? "[" + settings.attr + "]" : this;
$(selector).each(function() {
var $this = $(this);
var position = $this.attr(settings.attr);
var side = $("." + settings.attr + "-" + position);
if (settings.zIndexTop) {
side.addClass("pui-side-position-zindex-top");
}
var handle = function() {
if (settings.mask)
{
var mask = $(".pui-side-position-mask");
if (settings.maskFullOpacity)
{
mask.css({ opacity : 0 });
}
mask.fadeToggle(settings.speed);
if (!mask.is(":hidden"))
{
mask.bind($.clickOrTouch(), function() {
mask.fadeOut(settings.speed);
switch (position)
{
case "top":
side.animate({
top : "-" + side.outerHeight() + $(".pui-app-header").outerHeight() + "px",
opacity : "hide"
}, settings.speed);
case "bottom":
side.animate({bottom : "-" + side.outerHeight() + "px", opacity : "hide"}, settings.speed);
break;
case "right":
case "left":
default:
break;
}
return false;
});
}
}
if (position === "left" || position === "right")
{
side.height($("body").outerHeight());
}
if (settings.showMode === "fade")
{
side.fadeToggle(settings.speed);
}
else if (settings.showMode === "slide")
{
if (position === "left")
{
if (side.is(":hidden"))
{
side.css({ left : "-" + side.outerWidth() + "px"}).animate({ left : 0, opacity : "show"}, settings.speed);
}
else
{
side.animate({left : "-" + side.outerWidth() + "px", opacity : "hide"}, settings.speed);
}
}
if (position === "right")
{
if(side.is(":hidden"))
{
side.css({right : "-" + side.outerWidth() + "px"}).animate({right : 0, opacity : "show"}, settings.speed);
}
else
{
side.animate({
right : "-" + side.outerWidth() + "px",
opacity : "hide"
}, settings.speed);
}
}
if (position === "top")
{
if (side.is(":hidden"))
{
side.css({
top : "-" + side.outerHeight() + $(".pui-app-header").outerHeight() + "px"
}).animate({
top : $(".pui-app-header").outerHeight(),
opacity : "show"
}, settings.speed);
}
else
{
side.animate({
top : "-" + side.outerHeight() + $(".pui-app-header").outerHeight() + "px",
opacity : "hide"
}, settings.speed);
}
}
if (position === "bottom")
{
if (side.is(":hidden"))
{
side.css({
bottom : "-" + side.outerHeight() + "px"
}).animate({
bottom : 0,
opacity : "show"
}, settings.speed);
}
else
{
side.animate({
bottom : "-" + side.outerHeight() + "px",
opacity : "hide"
}, settings.speed);
}
}
}
else
{
side.toggle();
}
};
$this.bind($.clickOrTouch(), handle);
side.bind("click", handle);
});
};
})(PlaneUI);
(function ($) {
$.fn.sideSlide = function(options) {
var defaults = {
attr : "pui-side-slide",
speed : 300,
mask : false,
maskFullOpacity: false
};
var settings = $.extend(defaults, options);
$("["+settings.attr+"]").each(function() {
var $this = $(this);
var sideName = $this.attr(settings.attr);
var side = $("."+settings.attr+"-"+sideName);
var main = $(".pui-app-main");
var appLayout = $(".pui-app-layout");
$this.bind($.clickOrTouch(), function() {
if(sideName == "top" || sideName == "bottom") {
appLayout.css("overflow-y", "hidden");
} else {
appLayout.css("overflow-x", "hidden");
}
if(settings.mask)
{
var mask = main.find(".pui-mask-bg");
if(settings.maskFullOpacity) {
mask.css({opacity:0});
}
mask.fadeToggle(settings.speed);
if(!mask.is(":hidden"))
{
mask.bind($.clickOrTouch(), function() {
mask.fadeOut(settings.speed);
side.hide();
switch(sideName)
{
case "top":
case "bottom":
main.animate({marginTop : 0}, settings.speed, function(){
appLayout.css("overflow", "auto");
});
break;
case "right":
case "left":
default:
main.animate({marginLeft : 0}, settings.speed, function(){
appLayout.css("overflow", "auto");
});
break;
}
return false;
});
}
}
switch(sideName)
{
case "top":
side.toggle();
if(!side.is(":hidden")) {
main.animate({marginTop : side.outerHeight() + "px"}, settings.speed);
} else {
main.animate({marginTop : 0}, settings.speed, function(){
appLayout.css("overflow", "auto");
});
}
break;
case "bottom":
if(side.is(":hidden")) {
main.animate({marginTop : "-"+side.outerHeight() + "px"}, settings.speed, function() {
side.show();
});
} else {
side.hide();
main.animate({marginTop : 0}, settings.speed, function(){
appLayout.css("overflow", "auto");
});
}
break;
case "right":
if(side.is(":hidden")) {
main.animate({marginLeft : "-"+side.outerWidth() + "px"}, settings.speed, function(){
side.show();
});
} else {
side.hide();
main.animate({marginLeft : 0}, settings.speed, function(){
appLayout.css("overflow", "auto");
});
}
break;
case "left":
default:
side.toggle();
if(!side.is(":hidden")) {
main.animate({marginLeft : side.outerWidth() + "px"}, settings.speed);
} else {
main.animate({marginLeft : 0}, settings.speed, function(){
appLayout.css("overflow", "auto");
});
}
break;
}
return false;
});
});
};
})(PlaneUI);
(function($) {
$(function() {
$("pui-switch").each(function() {
var $this = $(this);
var values = $this.attr('value').split(',');
try
{
var texts = $this.attr('text').split(',');
}
catch(e)
{
alert("致命错误:请设置switch组件的text属性。");
return false;
}
var switched = $this.attr('switched');
var name = $this.attr('name');
var elements = "", switchedValue;
var innerHTML = $this.html();
$this.html('');
if(typeof(switched) == "undefined")
{
switched = values[0];
}
for (var i = 0, len = values.length; i < len; i++)
{
var isSwitched = (switched == values[i]) ? ' class="switched"' : '';
if(switched == values[i]) switchedValue = values[i];
elements += '
'+texts[i]+' ';
}
$this.append('
'+elements+' ');
$this.append('
');
if(innerHTML != '')
{
$this.append(innerHTML);
}
var item = $this.find('switches > span');
var input = $this.find('input');
if($this.attr('disabled') != 'disabled')
{
item.bind($.clickOrTouch(), function() {
$(this).addClass('switched').siblings().removeClass('switched');
input.val($(this).attr('value'));
});
}
});
});
})(PlaneUI);
(function($) {
$(function() {
$('pui-switch-slide').each(function() {
var $this = $(this);
var width = $this.attr('width');
var name = $this.attr('name');
var color = $this.attr('color');
var onColor = $this.attr('on-color');
var offColor = $this.attr('off-color');
var btn = $(this).find("span");
var animated = $this.attr('animated');
var value = (btn.attr("class") == 'off') ? 0 : 1;
var input = $('
');
$this.append(input);
if(typeof(width) != 'undefined')
{
$this.width(width);
}
if(typeof(color) != 'undefined')
{
$this.css({
backgroundColor : color,
color : color
});
}
var btnClassName = btn.attr("class");
if((btnClassName != 'off') && typeof(onColor) != 'undefined')
{
$this.css({
backgroundColor : onColor,
color : onColor
});
}
if((btnClassName == 'off') && typeof(offColor) != 'undefined')
{
$this.css({
backgroundColor : offColor,
color : offColor
});
}
$this.bind($.clickOrTouch(), function() {
if($this.attr('disabled') == 'disabled') return ;
if(typeof(animated) != 'undefined' && animated == 'true')
{
$this.addClass('pui-switch-slide-animation');
}
btn.toggleClass('off');
if((btn.attr("class") == 'off') && typeof(offColor) != 'undefined')
{
$this.css({
backgroundColor : offColor,
color : offColor
});
}
else
{
$this.css({
backgroundColor : onColor,
color : onColor
});
}
$(this).find("input").val( (btn.attr("class") == 'off') ? "0" : "1" );
var change = btn.attr("change");
btn.attr("change", btn.html());
btn.html(change);
return false;
});
});
});
})(PlaneUI);
(function($) {
$.fn.tab = function(options) {
var defaults = {
speed : 0,
ajax : false,
ajaxLoading : 'loading...',
cached : false,
showMode : "show",
callback : new Function
};
var settings = $.extend(defaults, options);
$(this).each(function() {
var $this = $(this);
var tabHead = $this.find(".pui-tab-head li");
var tabBox = $this.find(".pui-tab-box");
tabHead.bind($.clickOrTouch(), function() {
var thisHead = $(this);
if(thisHead.hasClass("disabled")) return ;
var index = thisHead.index();
var speed = settings.speed;
var showMode = settings.showMode;
var ajaxURL = thisHead.attr("tab-ajax-url");
var cached = thisHead.attr("tab-ajax-cached");
if(typeof(cached) == "undefined" || cached == "") {
cached = settings.cached;
}
thisHead.addClass("active").siblings().removeClass("active");
tabBox.removeClass("show");
if(showMode == "fade")
{
tabBox.eq(index).fadeIn(speed).siblings().fadeOut(speed);
}
else if(showMode == "slide")
{
tabBox.eq(index).slideDown(speed).siblings().slideUp(speed);
}
else if(showMode == "scroll-x")
{
var scrollbox = tabBox.parent();
var boxList = tabBox.parent();
var box = tabBox.eq(index);
var boxListWidth = 0;
tabBox.each(function(){
boxListWidth += $(this).outerWidth();
});
//console.log(boxList.html(), index * box[0].offsetWidth);
scrollbox.outerHeight(box.outerHeight());
boxList.outerWidth(boxListWidth + 50).animate({
marginLeft : "-"+(index * box.outerWidth()) + "px"
}, speed);
}
else if(showMode == "scroll-y")
{
var scrollbox = tabBox.parent();
var boxList = tabBox.parent();
var box = tabBox.eq(index);
var boxListHeight = 0;
tabBox.each(function(){
boxListHeight += $(this).outerHeight();
});
//console.log(boxList.html(), index * box.outerHeight());
scrollbox.outerHeight(box.outerHeight());
boxList.outerHeight(boxListHeight + 50).animate({
marginTop : "-"+(index * box.outerHeight()) + "px"
}, speed);
}
else
{
tabBox.eq(index).show(speed).siblings().hide(speed);
}
console.log(typeof(ajaxURL) != "undefined", settings.ajax , !settings.cached, thisHead.data("cached"));
if(typeof(ajaxURL) != "undefined" && settings.ajax && typeof(thisHead.data("cached")) == "undefined")
{
tabBox.eq(index).html(settings.ajaxLoading);
var ajaxURL = tabHead.eq(index).attr("tab-ajax-url");
$.get(ajaxURL, {}, function(data) {
if(cached)
{
thisHead.data("cached", true);
}
tabBox.eq(index).html(data);
settings.callback($this, tabHead, tabBox, index, settings);
});
}
if(!settings.ajax) {
settings.callback($this, tabHead, tabBox, index, settings);
}
});
});
$("[tab-onready-ajax*=true]").each(function() {
var $this = $(this);
var index = $this.index();
var tabBox = $this.parent().parent().find(".pui-tab-box");
var cached = $this.attr("tab-ajax-cached");
if(typeof(cached) == "undefined" || cached == "") {
cached = settings.cached;
}
tabBox.eq(index).html(settings.ajaxLoading);
var ajaxURL = $this.attr("tab-ajax-url");
if(typeof(ajaxURL) != "undefined" && typeof($this.data("cached")) == "undefined")
{
$.get(ajaxURL, {}, function(data) {
if(cached)
{
$this.data("cached", true);
}
tabBox.eq(index).html(data);
settings.callback($this, $this.parent(), tabBox, index, settings);
});
}
});
};
})(PlaneUI);
(function($){
$.fn.tooltip = function(options) {
var defaults = {
target : "",
auto : false,
position : ["bottom", "center"],
positionClassPrefix : "pui-tooltip-arrow-",
addClass : "pui-tooltip-bordered pui-tooltip-primary-light",
cached : false,
ajax : new Function,
showMode : "show",
touch : true,
content : new Function,
callback : new Function
};
var settings = $.extend(defaults, options);
var $this = $(this);
$this.each(function() {
var body = $("body");
var _this = $(this);
var parseJSON = function() {
var json = {};
var string = _this.attr("pui-tooltip");
try {
json = $.jsonDecode(string);
} catch(e) {
json = eval("("+string+")");
}
return json;
};
var jsonData = function(key) {
return parseJSON()[key];
};
var setJSONData = function(key, value) {
var json = parseJSON();
json[key] = value;
_this.attr("pui-tooltip", $.jsonEncode(json));
};
var target = function() {
return (typeof(jsonData("target")) == "undefined") ? settings.target : jsonData("target");
};
var content = jsonData("content");
var position = jsonData("position");
var addClass = jsonData("addClass");
var cached = jsonData("cached");
var callback = jsonData("callback");
var showMode = jsonData("showMode");
var touch = jsonData("touch");
if (typeof(content) == "undefined") {
content = settings.content;
}
if (typeof(position) == "undefined") {
position = settings.position;
}
if (typeof(addClass) == "undefined") {
addClass = settings.addClass;
}
if (typeof(cached) == "undefined") {
cached = settings.cached;
}
if (typeof(callback) == "undefined") {
callback = settings.callback;
}
if (typeof(showMode) == "undefined") {
showMode = settings.showMode;
}
if (typeof(touch) == "undefined") {
touch = settings.touch;
}
//console.log("cached", cached);
var tooltip, arrowHeight = 12;
var setTooltipStyle = function(tooltip) {
var arrow = "";
var posX = position[0];
var posY = position[1];
var _top = _left = 0;
var width = _this[0].offsetWidth;
var height = _this[0].offsetHeight;
var top = _this.offset().top;
var left = _this.offset().left;
var tooltipWidth = tooltip[0].offsetWidth;
var tooltipHeight = tooltip[0].offsetHeight;
var windowWidth = (document.all) ? document.getElementsByTagName("html")[0].offsetWidth : window.innerWidth;
var windowHeight = (document.all) ? document.getElementsByTagName("html")[0].offsetHeight : window.innerHeight;
//console.log("windowWidth=>", windowWidth, "windowHeight=>", windowHeight);
//console.log("tooltip.offsetHeight", _this[0].offsetWidth, tooltip[0].offsetHeight, tooltip.width());
//console.log(position, "width=>", width, "height=>", height, "tooltip.width=>", tooltipWidth, "tooltip.height=>", tooltipHeight, "top=>", top, "left=>", left, "_top=>", _top, "_left=>", _left);
var arrowGetPosition = function(arrow) {
var data = {};
switch(arrow) {
case "tc":
data = {
top : top + height + arrowHeight,
left : left + (width - tooltipWidth) / 2,
posX : "bottom",
posY : "center"
}
break;
case "tl":
data = {
top : top + height + arrowHeight,
left : left,
posX : "bottom",
posY : "left"
}
break;
case "tr":
data = {
top : top + height + arrowHeight,
left : left + width - tooltipWidth,
posX : "bottom",
posY : "right"
}
break;
case "bc":
data = {
top : top - tooltipHeight - arrowHeight,
left : left + (width - tooltipWidth) / 2,
posX : "top",
posY : "center"
}
break;
case "bl":
data = {
top : top - tooltipHeight - arrowHeight,
left : left,
posX : "top",
posY : "left"
}
break;
case "br":
data = {
top : top - tooltipHeight - arrowHeight,
left : left + width - tooltipWidth,
posX : "top",
posY : "right"
}
break;
case "lc":
data = {
top : top + (height - tooltipHeight) / 2,
left : left + (width + arrowHeight),
posX : "right",
posY : "center"
}
break;
case "lt":
data = {
top : top,
left : left + (width + arrowHeight),
posX : "right",
posY : "top"
}
break;
case "lb":
data = {
top : top + height - tooltipHeight,
left : left + (width + arrowHeight),
posX : "right",
posY : "bottom"
}
break;
case "rc":
data = {
top : top + (height - tooltipHeight) / 2,
left : left - (tooltipWidth + arrowHeight),
posX : "left",
posY : "center"
}
break;
case "rt":
data = {
top : top,
left : left - (tooltipWidth + arrowHeight),
posX : "left",
posY : "top"
}
break;
case "rb":
data = {
top : top + height - tooltipHeight,
left : left - (tooltipWidth + arrowHeight),
posX : "left",
posY : "bottom"
}
break;
};
return data;
};
if(posX == "top" && posY == "center") {
arrow = "bc";
}
if(posX == "top" && posY == "left") {
arrow = "bl";
}
if(posX == "top" && posY == "right") {
arrow = "br";
}
if(posX == "bottom" && posY == "center") {
arrow = "tc";
}
if(posX == "bottom" && posY == "left") {
arrow = "tl";
}
if(posX == "bottom" && posY == "right") {
arrow = "tr";
}
if(posX == "left" && posY == "center") {
arrow = "rc";
}
if(posX == "left" && posY == "top") {
arrow = "rt";
}
if(posX == "left" && posY == "bottom") {
arrow = "rb";
}
if(posX == "right" && posY == "center") {
arrow = "lc";
}
if(posX == "right" && posY == "top") {
arrow = "lt";
}
if(posX == "right" && posY == "bottom") {
arrow = "lb";
}
_top = arrowGetPosition(arrow).top;
_left = arrowGetPosition(arrow).left;
/*var newArrow = "";
console.log("_top < 0", _top - document.body.scrollTop < 0, _top, document.body.scrollTop);
console.log("_left < 0", (_left - tooltipWidth) < 0);
if((_top - document.body.scrollTop) < 0 && (_left - tooltipWidth) < 0) {
arrow = "tl";
}
if((_top + tooltipHeight) > windowHeight && (_left - tooltipWidth) < 0) {
arrow = "bl";
}*/
/*if(_top < 0) {
arrow = "tc";
}
if(_top + tooltipHeight > windowHeight) {
arrow = "bc";
}
if(_left < 0) {
arrow = "rc";
}
if(_left + tooltipWidth > windowWidth) {
arrow = "rc";
}*/
//_top = arrowGetPosition(arrow).top;
//_left = arrowGetPosition(arrow).left;
//posX = arrowGetPosition(arrow).posX;
//posY = arrowGetPosition(arrow).posY;
//console.log(position, "width=>", width, "height=>", height, "tooltip.width=>", tooltipWidth, "tooltip.height=>", tooltipHeight, "top=>", top, "left=>", left, "_top=>", _top, "_left=>", _left);
// 箭头居中的设置
var arrowClassName = settings.positionClassPrefix + arrow;
if (posY == "center") {
var head = document.getElementsByTagName("head")[0];
var style = document.createElement('style');
style.id = tooltip.attr("id") + "-style";
var styleText = "";
styleText += "#"+tooltip.attr("id") + "." + arrowClassName+":before, ";
styleText += "#"+tooltip.attr("id") + "." + arrowClassName+":after";
if(posX == "top" && posY == "center") {
styleText += "{left:"+((tooltipWidth / 2) - 7)+"px;}";
}
if(posX == "bottom" && posY == "center") {
styleText += "{left:"+((tooltipWidth / 2) - 7)+"px;}";
}
if(posX == "left" && posY == "center") {
styleText += "{top:"+((tooltipHeight / 2) - 7)+"px;}";
}
if(posX == "right" && posY == "center") {
styleText += "{top:"+((tooltipHeight / 2) - 7)+"px;}";
}
style.innerText = styleText;
head.appendChild(style);
}
//document.styleSheets[0].addRule('.tooltip-arrow-bc:before, .tooltip-arrow-bc:after', 'top:0;left:0;background:red;');
tooltip.addClass(arrowClassName)
.css({
position: "absolute",
top : _top,
left : _left
});
};
var showAction = function() {
//console.log("mouseenter", target(), addClass, content, cached, showMode);
if (typeof(target()) == "undefined" || target() == "")
{
tooltip = $('
');
tooltip.data("id", "tooltip-" + (new Date()).getTime() );
tooltip.attr("id", tooltip.data("id") );
if(cached)
{
setJSONData("target", "#" + tooltip.data("id") );
}
body.append(tooltip);
if(typeof(content) == "function") {
content(_this, tooltip, setTooltipStyle);
} else {
tooltip.html(content);
setTooltipStyle(tooltip);
}
}
else
{
tooltip = $(target());
tooltip.removeClass('pui-hide');
if(!cached && !tooltip.data("targetStyled"))
{
tooltip.data("targetStyled", true);
setTooltipStyle(tooltip);
}
}
tooltip[ (showMode == "fade") ? "fadeIn" : "show" ]();
};
var hideAction = function() {
tooltip[ (showMode == "fade") ? "fadeOut" : "hide" ]();
if (typeof(target()) == "undefined" && !cached || target() == "")
{
$("#"+tooltip.attr("id") + "-style").remove();
tooltip.remove();
}
callback(_this, tooltip);
};
_this.bind({
"mouseenter" : showAction,
"mouseleave" : hideAction
});
if(touch) {
_this.bind({
"touchstart" : showAction,
"touchend" : hideAction,
"touchcancel": hideAction
});
}
});
};
})(PlaneUI);
/*!
* Modernizr v2.8.3
* www.modernizr.com
*
* Copyright (c) Faruk Ates, Paul Irish, Alex Sexton
* Available under the BSD and MIT licenses: www.modernizr.com/license/
*/
/*
* Modernizr tests which native CSS3 and HTML5 features are available in
* the current UA and makes the results available to you in two ways:
* as properties on a global Modernizr object, and as classes on the
* element. This information allows you to progressively enhance
* your pages with a granular level of control over the experience.
*
* Modernizr has an optional (not included) conditional resource loader
* called Modernizr.load(), based on Yepnope.js (yepnopejs.com).
* To get a build that includes Modernizr.load(), as well as choosing
* which tests to include, go to www.modernizr.com/download/
*
* Authors Faruk Ates, Paul Irish, Alex Sexton
* Contributors Ryan Seddon, Ben Alman
*/
window.Modernizr = (function( window, document, undefined ) {
var version = '2.8.3',
Modernizr = {},
/*>>cssclasses*/
// option for enabling the HTML classes to be added
enableClasses = true,
/*>>cssclasses*/
docElement = document.documentElement,
/**
* Create our "modernizr" element that we do most feature tests on.
*/
mod = 'modernizr',
modElem = document.createElement(mod),
mStyle = modElem.style,
/**
* Create the input element for various Web Forms feature tests.
*/
inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ ,
/*>>smile*/
smile = ':)',
/*>>smile*/
toString = {}.toString,
// TODO :: make the prefixes more granular
/*>>prefixes*/
// List of property values to set for css tests. See ticket #21
prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
/*>>prefixes*/
/*>>domprefixes*/
// Following spec is to expose vendor-specific style properties as:
// elem.style.WebkitBorderRadius
// and the following would be incorrect:
// elem.style.webkitBorderRadius
// Webkit ghosts their properties in lowercase but Opera & Moz do not.
// Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
// erik.eae.net/archives/2008/03/10/21.48.10/
// More here: github.com/Modernizr/Modernizr/issues/issue/21
omPrefixes = 'Webkit Moz O ms',
cssomPrefixes = omPrefixes.split(' '),
domPrefixes = omPrefixes.toLowerCase().split(' '),
/*>>domprefixes*/
/*>>ns*/
ns = {'svg': 'http://www.w3.org/2000/svg'},
/*>>ns*/
tests = {},
inputs = {},
attrs = {},
classes = [],
slice = classes.slice,
featureName, // used in testing loop
/*>>teststyles*/
// Inject element with style element and some CSS rules
injectElementWithStyles = function( rule, callback, nodes, testnames ) {
var style, ret, node, docOverflow,
div = document.createElement('div'),
// After page load injecting a fake body doesn't work so check if body exists
body = document.body,
// IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it.
fakeBody = body || document.createElement('body');
if ( parseInt(nodes, 10) ) {
// In order not to give false positives we create a node for each test
// This also allows the method to scale for unspecified uses
while ( nodes-- ) {
node = document.createElement('div');
node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
div.appendChild(node);
}
}
// '].join('');
div.id = mod;
// IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.
// Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
(body ? div : fakeBody).innerHTML += style;
fakeBody.appendChild(div);
if ( !body ) {
//avoid crashing IE8, if background image is used
fakeBody.style.background = '';
//Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
fakeBody.style.overflow = 'hidden';
docOverflow = docElement.style.overflow;
docElement.style.overflow = 'hidden';
docElement.appendChild(fakeBody);
}
ret = callback(div, rule);
// If this is done after page load we don't want to remove the body so check if body exists
if ( !body ) {
fakeBody.parentNode.removeChild(fakeBody);
docElement.style.overflow = docOverflow;
} else {
div.parentNode.removeChild(div);
}
return !!ret;
},
/*>>teststyles*/
/*>>mq*/
// adapted from matchMedia polyfill
// by Scott Jehl and Paul Irish
// gist.github.com/786768
testMediaQuery = function( mq ) {
var matchMedia = window.matchMedia || window.msMatchMedia;
if ( matchMedia ) {
return matchMedia(mq) && matchMedia(mq).matches || false;
}
var bool;
injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) {
bool = (window.getComputedStyle ?
getComputedStyle(node, null) :
node.currentStyle)['position'] == 'absolute';
});
return bool;
},
/*>>mq*/
/*>>hasevent*/
//
// isEventSupported determines if a given element supports the given event
// kangax.github.com/iseventsupported/
//
// The following results are known incorrects:
// Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative
// Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333
// ...
isEventSupported = (function() {
var TAGNAMES = {
'select': 'input', 'change': 'input',
'submit': 'form', 'reset': 'form',
'error': 'img', 'load': 'img', 'abort': 'img'
};
function isEventSupported( eventName, element ) {
element = element || document.createElement(TAGNAMES[eventName] || 'div');
eventName = 'on' + eventName;
// When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
var isSupported = eventName in element;
if ( !isSupported ) {
// If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
if ( !element.setAttribute ) {
element = document.createElement('div');
}
if ( element.setAttribute && element.removeAttribute ) {
element.setAttribute(eventName, '');
isSupported = is(element[eventName], 'function');
// If property was created, "remove it" (by setting value to `undefined`)
if ( !is(element[eventName], 'undefined') ) {
element[eventName] = undefined;
}
element.removeAttribute(eventName);
}
}
element = null;
return isSupported;
}
return isEventSupported;
})(),
/*>>hasevent*/
// TODO :: Add flag for hasownprop ? didn't last time
// hasOwnProperty shim by kangax needed for Safari 2.0 support
_hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
hasOwnProp = function (object, property) {
return _hasOwnProperty.call(object, property);
};
}
else {
hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
};
}
// Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js
// es5.github.com/#x15.3.4.5
if (!Function.prototype.bind) {
Function.prototype.bind = function bind(that) {
var target = this;
if (typeof target != "function") {
throw new TypeError();
}
var args = slice.call(arguments, 1),
bound = function () {
if (this instanceof bound) {
var F = function(){};
F.prototype = target.prototype;
var self = new F();
var result = target.apply(
self,
args.concat(slice.call(arguments))
);
if (Object(result) === result) {
return result;
}
return self;
} else {
return target.apply(
that,
args.concat(slice.call(arguments))
);
}
};
return bound;
};
}
/**
* setCss applies given styles to the Modernizr DOM node.
*/
function setCss( str ) {
mStyle.cssText = str;
}
/**
* setCssAll extrapolates all vendor-specific css strings.
*/
function setCssAll( str1, str2 ) {
return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
}
/**
* is returns a boolean for if typeof obj is exactly type.
*/
function is( obj, type ) {
return typeof obj === type;
}
/**
* contains returns a boolean for if substr is found within str.
*/
function contains( str, substr ) {
return !!~('' + str).indexOf(substr);
}
/*>>testprop*/
// testProps is a generic CSS / DOM property test.
// In testing support for a given CSS property, it's legit to test:
// `elem.style[styleName] !== undefined`
// If the property is supported it will return an empty string,
// if unsupported it will return undefined.
// We'll take advantage of this quick test and skip setting a style
// on our modernizr element, but instead just testing undefined vs
// empty string.
// Because the testing of the CSS property names (with "-", as
// opposed to the camelCase DOM properties) is non-portable and
// non-standard but works in WebKit and IE (but not Gecko or Opera),
// we explicitly reject properties with dashes so that authors
// developing in WebKit or IE first don't end up with
// browser-specific content by accident.
function testProps( props, prefixed ) {
for ( var i in props ) {
var prop = props[i];
if ( !contains(prop, "-") && mStyle[prop] !== undefined ) {
return prefixed == 'pfx' ? prop : true;
}
}
return false;
}
/*>>testprop*/
// TODO :: add testDOMProps
/**
* testDOMProps is a generic DOM property test; if a browser supports
* a certain property, it won't return undefined for it.
*/
function testDOMProps( props, obj, elem ) {
for ( var i in props ) {
var item = obj[props[i]];
if ( item !== undefined) {
// return the property name as a string
if (elem === false) return props[i];
// let's bind a function
if (is(item, 'function')){
// default to autobind unless override
return item.bind(elem || obj);
}
// return the unbound function or obj or value
return item;
}
}
return false;
}
/*>>testallprops*/
/**
* testPropsAll tests a list of DOM properties we want to check against.
* We specify literally ALL possible (known and/or likely) properties on
* the element including the non-vendor prefixed one, for forward-
* compatibility.
*/
function testPropsAll( prop, prefixed, elem ) {
var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
// did they call .prefixed('boxSizing') or are we just testing a prop?
if(is(prefixed, "string") || is(prefixed, "undefined")) {
return testProps(props, prefixed);
// otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
} else {
props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
return testDOMProps(props, prefixed, elem);
}
}
/*>>testallprops*/
/**
* Tests
* -----
*/
// The *new* flexbox
// dev.w3.org/csswg/css3-flexbox
tests['flexbox'] = function() {
return testPropsAll('flexWrap');
};
// The *old* flexbox
// www.w3.org/TR/2009/WD-css3-flexbox-20090723/
tests['flexboxlegacy'] = function() {
return testPropsAll('boxDirection');
};
// On the S60 and BB Storm, getContext exists, but always returns undefined
// so we actually have to call getContext() to verify
// github.com/Modernizr/Modernizr/issues/issue/97/
tests['canvas'] = function() {
var elem = document.createElement('canvas');
return !!(elem.getContext && elem.getContext('2d'));
};
tests['canvastext'] = function() {
return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
};
// webk.it/70117 is tracking a legit WebGL feature detect proposal
// We do a soft detect which may false positive in order to avoid
// an expensive context creation: bugzil.la/732441
tests['webgl'] = function() {
return !!window.WebGLRenderingContext;
};
/*
* The Modernizr.touch test only indicates if the browser supports
* touch events, which does not necessarily reflect a touchscreen
* device, as evidenced by tablets running Windows 7 or, alas,
* the Palm Pre / WebOS (touch) phones.
*
* Additionally, Chrome (desktop) used to lie about its support on this,
* but that has since been rectified: crbug.com/36415
*
* We also test for Firefox 4 Multitouch Support.
*
* For more info, see: modernizr.github.com/Modernizr/touch.html
*/
tests['touch'] = function() {
var bool;
if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
bool = true;
} else {
injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) {
bool = node.offsetTop === 9;
});
}
return bool;
};
// geolocation is often considered a trivial feature detect...
// Turns out, it's quite tricky to get right:
//
// Using !!navigator.geolocation does two things we don't want. It:
// 1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513
// 2. Disables page caching in WebKit: webk.it/43956
//
// Meanwhile, in Firefox < 8, an about:config setting could expose
// a false positive that would throw an exception: bugzil.la/688158
tests['geolocation'] = function() {
return 'geolocation' in navigator;
};
tests['postmessage'] = function() {
return !!window.postMessage;
};
// Chrome incognito mode used to throw an exception when using openDatabase
// It doesn't anymore.
tests['websqldatabase'] = function() {
return !!window.openDatabase;
};
// Vendors had inconsistent prefixing with the experimental Indexed DB:
// - Webkit's implementation is accessible through webkitIndexedDB
// - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB
// For speed, we don't test the legacy (and beta-only) indexedDB
tests['indexedDB'] = function() {
return !!testPropsAll("indexedDB", window);
};
// documentMode logic from YUI to filter out IE8 Compat Mode
// which false positives.
tests['hashchange'] = function() {
return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7);
};
// Per 1.6:
// This used to be Modernizr.historymanagement but the longer
// name has been deprecated in favor of a shorter and property-matching one.
// The old API is still available in 1.6, but as of 2.0 will throw a warning,
// and in the first release thereafter disappear entirely.
tests['history'] = function() {
return !!(window.history && history.pushState);
};
tests['draganddrop'] = function() {
var div = document.createElement('div');
return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
};
// FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10
// will be supported until FF19 (2/12/13), at which time, ESR becomes FF17.
// FF10 still uses prefixes, so check for it until then.
// for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/
tests['websockets'] = function() {
return 'WebSocket' in window || 'MozWebSocket' in window;
};
// css-tricks.com/rgba-browser-support/
tests['rgba'] = function() {
// Set an rgba() color and check the returned value
setCss('background-color:rgba(150,255,150,.5)');
return contains(mStyle.backgroundColor, 'rgba');
};
tests['hsla'] = function() {
// Same as rgba(), in fact, browsers re-map hsla() to rgba() internally,
// except IE9 who retains it as hsla
setCss('background-color:hsla(120,40%,100%,.5)');
return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla');
};
tests['multiplebgs'] = function() {
// Setting multiple images AND a color on the background shorthand property
// and then querying the style.background property value for the number of
// occurrences of "url(" is a reliable method for detecting ACTUAL support for this!
setCss('background:url(https://),url(https://),red url(https://)');
// If the UA supports multiple backgrounds, there should be three occurrences
// of the string "url(" in the return value for elemStyle.background
return (/(url\s*\(.*?){3}/).test(mStyle.background);
};
// this will false positive in Opera Mini
// github.com/Modernizr/Modernizr/issues/396
tests['backgroundsize'] = function() {
return testPropsAll('backgroundSize');
};
tests['borderimage'] = function() {
return testPropsAll('borderImage');
};
// Super comprehensive table about all the unique implementations of
// border-radius: muddledramblings.com/table-of-css3-border-radius-compliance
tests['borderradius'] = function() {
return testPropsAll('borderRadius');
};
// WebOS unfortunately false positives on this test.
tests['boxshadow'] = function() {
return testPropsAll('boxShadow');
};
// FF3.0 will false positive on this test
tests['textshadow'] = function() {
return document.createElement('div').style.textShadow === '';
};
tests['opacity'] = function() {
// Browsers that actually have CSS Opacity implemented have done so
// according to spec, which means their return values are within the
// range of [0.0,1.0] - including the leading zero.
setCssAll('opacity:.55');
// The non-literal . in this regex is intentional:
// German Chrome returns this value as 0,55
// github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632
return (/^0.55$/).test(mStyle.opacity);
};
// Note, Android < 4 will pass this test, but can only animate
// a single property at a time
// goo.gl/v3V4Gp
tests['cssanimations'] = function() {
return testPropsAll('animationName');
};
tests['csscolumns'] = function() {
return testPropsAll('columnCount');
};
tests['cssgradients'] = function() {
/**
* For CSS Gradients syntax, please see:
* webkit.org/blog/175/introducing-css-gradients/
* developer.mozilla.org/en/CSS/-moz-linear-gradient
* developer.mozilla.org/en/CSS/-moz-radial-gradient
* dev.w3.org/csswg/css3-images/#gradients-
*/
var str1 = 'background-image:',
str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',
str3 = 'linear-gradient(left top,#9f9, white);';
setCss(
// legacy webkit syntax (FIXME: remove when syntax not in use anymore)
(str1 + '-webkit- '.split(' ').join(str2 + str1) +
// standard syntax // trailing 'background-image:'
prefixes.join(str3 + str1)).slice(0, -str1.length)
);
return contains(mStyle.backgroundImage, 'gradient');
};
tests['cssreflections'] = function() {
return testPropsAll('boxReflect');
};
tests['csstransforms'] = function() {
return !!testPropsAll('transform');
};
tests['csstransforms3d'] = function() {
var ret = !!testPropsAll('perspective');
// Webkit's 3D transforms are passed off to the browser's own graphics renderer.
// It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in
// some conditions. As a result, Webkit typically recognizes the syntax but
// will sometimes throw a false positive, thus we must do a more thorough check:
if ( ret && 'webkitPerspective' in docElement.style ) {
// Webkit allows this media query to succeed only if the feature is enabled.
// `@media (transform-3d),(-webkit-transform-3d){ ... }`
injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) {
ret = node.offsetLeft === 9 && node.offsetHeight === 3;
});
}
return ret;
};
tests['csstransitions'] = function() {
return testPropsAll('transition');
};
/*>>fontface*/
// @font-face detection routine by Diego Perini
// javascript.nwbox.com/CSSSupport/
// false positives:
// WebOS github.com/Modernizr/Modernizr/issues/342
// WP7 github.com/Modernizr/Modernizr/issues/538
tests['fontface'] = function() {
var bool;
injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) {
var style = document.getElementById('smodernizr'),
sheet = style.sheet || style.styleSheet,
cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : '';
bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0;
});
return bool;
};
/*>>fontface*/
// CSS generated content detection
tests['generatedcontent'] = function() {
var bool;
injectElementWithStyles(['#',mod,'{font:0/0 a}#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) {
bool = node.offsetHeight >= 3;
});
return bool;
};
// These tests evaluate support of the video/audio elements, as well as
// testing what types of content they support.
//
// We're using the Boolean constructor here, so that we can extend the value
// e.g. Modernizr.video // true
// Modernizr.video.ogg // 'probably'
//
// Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
// thx to NielsLeenheer and zcorpan
// Note: in some older browsers, "no" was a return value instead of empty string.
// It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2
// It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5
tests['video'] = function() {
var elem = document.createElement('video'),
bool = false;
// IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224
try {
if ( bool = !!elem.canPlayType ) {
bool = new Boolean(bool);
bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,'');
// Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546
bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,'');
bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,'');
}
} catch(e) { }
return bool;
};
tests['audio'] = function() {
var elem = document.createElement('audio'),
bool = false;
try {
if ( bool = !!elem.canPlayType ) {
bool = new Boolean(bool);
bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,'');
// Mimetypes accepted:
// developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements
// bit.ly/iphoneoscodecs
bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,'');
bool.m4a = ( elem.canPlayType('audio/x-m4a;') ||
elem.canPlayType('audio/aac;')) .replace(/^no$/,'');
}
} catch(e) { }
return bool;
};
// In FF4, if disabled, window.localStorage should === null.
// Normally, we could not test that directly and need to do a
// `('localStorage' in window) && ` test first because otherwise Firefox will
// throw bugzil.la/365772 if cookies are disabled
// Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem
// will throw the exception:
// QUOTA_EXCEEDED_ERRROR DOM Exception 22.
// Peculiarly, getItem and removeItem calls do not throw.
// Because we are forced to try/catch this, we'll go aggressive.
// Just FWIW: IE8 Compat mode supports these features completely:
// www.quirksmode.org/dom/html5.html
// But IE8 doesn't support either with local files
tests['localstorage'] = function() {
try {
localStorage.setItem(mod, mod);
localStorage.removeItem(mod);
return true;
} catch(e) {
return false;
}
};
tests['sessionstorage'] = function() {
try {
sessionStorage.setItem(mod, mod);
sessionStorage.removeItem(mod);
return true;
} catch(e) {
return false;
}
};
tests['webworkers'] = function() {
return !!window.Worker;
};
tests['applicationcache'] = function() {
return !!window.applicationCache;
};
// Thanks to Erik Dahlstrom
tests['svg'] = function() {
return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;
};
// specifically for SVG inline in HTML, not within XHTML
// test page: paulirish.com/demo/inline-svg
tests['inlinesvg'] = function() {
var div = document.createElement('div');
div.innerHTML = '
';
return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
};
// SVG SMIL animation
tests['smil'] = function() {
return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate')));
};
// This test is only for clip paths in SVG proper, not clip paths on HTML content
// demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg
// However read the comments to dig into applying SVG clippaths to HTML content here:
// github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491
tests['svgclippaths'] = function() {
return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));
};
/*>>webforms*/
// input features and input types go directly onto the ret object, bypassing the tests loop.
// Hold this guy to execute in a moment.
function webforms() {
/*>>input*/
// Run through HTML5's new input attributes to see if the UA understands any.
// We're using f which is the
element created early on
// Mike Taylr has created a comprehensive resource for testing these attributes
// when applied to all input types:
// miketaylr.com/code/input-type-attr.html
// spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
// Only input placeholder is tested while textarea's placeholder is not.
// Currently Safari 4 and Opera 11 have support only for the input placeholder
// Both tests are available in feature-detects/forms-placeholder.js
Modernizr['input'] = (function( props ) {
for ( var i = 0, len = props.length; i < len; i++ ) {
attrs[ props[i] ] = !!(props[i] in inputElem);
}
if (attrs.list){
// safari false positive's on datalist: webk.it/74252
// see also github.com/Modernizr/Modernizr/issues/146
attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement);
}
return attrs;
})('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '));
/*>>input*/
/*>>inputtypes*/
// Run through HTML5's new input types to see if the UA understands any.
// This is put behind the tests runloop because it doesn't return a
// true/false like all the other tests; instead, it returns an object
// containing each input type with its corresponding true/false value
// Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/
Modernizr['inputtypes'] = (function(props) {
for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
inputElem.setAttribute('type', inputElemType = props[i]);
bool = inputElem.type !== 'text';
// We first check to see if the type we give it sticks..
// If the type does, we feed it a textual value, which shouldn't be valid.
// If the value doesn't stick, we know there's input sanitization which infers a custom UI
if ( bool ) {
inputElem.value = smile;
inputElem.style.cssText = 'position:absolute;visibility:hidden;';
if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) {
docElement.appendChild(inputElem);
defaultView = document.defaultView;
// Safari 2-4 allows the smiley as a value, despite making a slider
bool = defaultView.getComputedStyle &&
defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&
// Mobile android web browser has false positive, so must
// check the height to see if the widget is actually there.
(inputElem.offsetHeight !== 0);
docElement.removeChild(inputElem);
} else if ( /^(search|tel)$/.test(inputElemType) ){
// Spec doesn't define any special parsing or detectable UI
// behaviors so we pass these through as true
// Interestingly, opera fails the earlier test, so it doesn't
// even make it here.
} else if ( /^(url|email)$/.test(inputElemType) ) {
// Real url and email support comes with prebaked validation.
bool = inputElem.checkValidity && inputElem.checkValidity() === false;
} else {
// If the upgraded input compontent rejects the :) text, we got a winner
bool = inputElem.value != smile;
}
}
inputs[ props[i] ] = !!bool;
}
return inputs;
})('search tel url email datetime date month week time datetime-local number range color'.split(' '));
/*>>inputtypes*/
}
/*>>webforms*/
// End of test definitions
// -----------------------
// Run through all tests and detect their support in the current UA.
// todo: hypothetically we could be doing an array of tests and use a basic loop here.
for ( var feature in tests ) {
if ( hasOwnProp(tests, feature) ) {
// run the test, throw the return value into the Modernizr,
// then based on that boolean, define an appropriate className
// and push it into an array of classes we'll join later.
featureName = feature.toLowerCase();
Modernizr[featureName] = tests[feature]();
classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
}
}
/*>>webforms*/
// input tests need to run.
Modernizr.input || webforms();
/*>>webforms*/
/**
* addTest allows the user to define their own feature tests
* the result will be added onto the Modernizr object,
* as well as an appropriate className set on the html element
*
* @param feature - String naming the feature
* @param test - Function returning true if feature is supported, false if not
*/
Modernizr.addTest = function ( feature, test ) {
if ( typeof feature == 'object' ) {
for ( var key in feature ) {
if ( hasOwnProp( feature, key ) ) {
Modernizr.addTest( key, feature[ key ] );
}
}
} else {
feature = feature.toLowerCase();
if ( Modernizr[feature] !== undefined ) {
// we're going to quit if you're trying to overwrite an existing test
// if we were to allow it, we'd do this:
// var re = new RegExp("\\b(no-)?" + feature + "\\b");
// docElement.className = docElement.className.replace( re, '' );
// but, no rly, stuff 'em.
return Modernizr;
}
test = typeof test == 'function' ? test() : test;
if (typeof enableClasses !== "undefined" && enableClasses) {
docElement.className += ' ' + (test ? '' : 'no-') + feature;
}
Modernizr[feature] = test;
}
return Modernizr; // allow chaining.
};
// Reset modElem.cssText to nothing to reduce memory footprint.
setCss('');
modElem = inputElem = null;
/*>>shiv*/
/**
* @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
;(function(window, document) {
/*jshint evil:true */
/** version */
var version = '3.7.0';
/** Preset options */
var options = window.html5 || {};
/** Used to skip problem elements */
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
/** Not all elements can be cloned in IE **/
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
/** Detect whether the browser supports default html5 styles */
var supportsHtml5Styles;
/** Name of the expando, to work with multiple documents or to re-shiv one document */
var expando = '_html5shiv';
/** The id for the the documents expando */
var expanID = 0;
/** Cached data for each document */
var expandoData = {};
/** Detect whether the browser supports unknown elements */
var supportsUnknownElements;
(function() {
try {
var a = document.createElement('a');
a.innerHTML = '
';
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
supportsHtml5Styles = ('hidden' in a);
supportsUnknownElements = a.childNodes.length == 1 || (function() {
// assign a false positive if unable to shiv
(document.createElement)('a');
var frag = document.createDocumentFragment();
return (
typeof frag.cloneNode == 'undefined' ||
typeof frag.createDocumentFragment == 'undefined' ||
typeof frag.createElement == 'undefined'
);
}());
} catch(e) {
// assign a false positive if detection fails => unable to shiv
supportsHtml5Styles = true;
supportsUnknownElements = true;
}
}());
/*--------------------------------------------------------------------------*/
/**
* Creates a style sheet with the given CSS text and adds it to the document.
* @private
* @param {Document} ownerDocument The document.
* @param {String} cssText The CSS text.
* @returns {StyleSheet} The style element.
*/
function addStyleSheet(ownerDocument, cssText) {
var p = ownerDocument.createElement('p'),
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
p.innerHTML = 'x';
return parent.insertBefore(p.lastChild, parent.firstChild);
}
/**
* Returns the value of `html5.elements` as an array.
* @private
* @returns {Array} An array of shived element node names.
*/
function getElements() {
var elements = html5.elements;
return typeof elements == 'string' ? elements.split(' ') : elements;
}
/**
* Returns the data associated to the given document
* @private
* @param {Document} ownerDocument The document.
* @returns {Object} An object of data.
*/
function getExpandoData(ownerDocument) {
var data = expandoData[ownerDocument[expando]];
if (!data) {
data = {};
expanID++;
ownerDocument[expando] = expanID;
expandoData[expanID] = data;
}
return data;
}
/**
* returns a shived element for the given nodeName and document
* @memberOf html5
* @param {String} nodeName name of the element
* @param {Document} ownerDocument The context document.
* @returns {Object} The shived element.
*/
function createElement(nodeName, ownerDocument, data){
if (!ownerDocument) {
ownerDocument = document;
}
if(supportsUnknownElements){
return ownerDocument.createElement(nodeName);
}
if (!data) {
data = getExpandoData(ownerDocument);
}
var node;
if (data.cache[nodeName]) {
node = data.cache[nodeName].cloneNode();
} else if (saveClones.test(nodeName)) {
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
} else {
node = data.createElem(nodeName);
}
// Avoid adding some elements to fragments in IE < 9 because
// * Attributes like `name` or `type` cannot be set/changed once an element
// is inserted into a document/fragment
// * Link elements with `src` attributes that are inaccessible, as with
// a 403 response, will cause the tab/window to crash
// * Script elements appended to fragments will execute when their `src`
// or `text` property is set
return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
}
/**
* returns a shived DocumentFragment for the given document
* @memberOf html5
* @param {Document} ownerDocument The context document.
* @returns {Object} The shived DocumentFragment.
*/
function createDocumentFragment(ownerDocument, data){
if (!ownerDocument) {
ownerDocument = document;
}
if(supportsUnknownElements){
return ownerDocument.createDocumentFragment();
}
data = data || getExpandoData(ownerDocument);
var clone = data.frag.cloneNode(),
i = 0,
elems = getElements(),
l = elems.length;
for(;i
>shiv*/
// Assign private properties to the return object with prefix
Modernizr._version = version;
// expose these for the plugin API. Look in the source for how to join() them against your input
/*>>prefixes*/
Modernizr._prefixes = prefixes;
/*>>prefixes*/
/*>>domprefixes*/
Modernizr._domPrefixes = domPrefixes;
Modernizr._cssomPrefixes = cssomPrefixes;
/*>>domprefixes*/
/*>>mq*/
// Modernizr.mq tests a given media query, live against the current state of the window
// A few important notes:
// * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false
// * A max-width or orientation query will be evaluated against the current state, which may change later.
// * You must specify values. Eg. If you are testing support for the min-width media query use:
// Modernizr.mq('(min-width:0)')
// usage:
// Modernizr.mq('only screen and (max-width:768)')
Modernizr.mq = testMediaQuery;
/*>>mq*/
/*>>hasevent*/
// Modernizr.hasEvent() detects support for a given event, with an optional element to test on
// Modernizr.hasEvent('gesturestart', elem)
Modernizr.hasEvent = isEventSupported;
/*>>hasevent*/
/*>>testprop*/
// Modernizr.testProp() investigates whether a given style property is recognized
// Note that the property names must be provided in the camelCase variant.
// Modernizr.testProp('pointerEvents')
Modernizr.testProp = function(prop){
return testProps([prop]);
};
/*>>testprop*/
/*>>testallprops*/
// Modernizr.testAllProps() investigates whether a given style property,
// or any of its vendor-prefixed variants, is recognized
// Note that the property names must be provided in the camelCase variant.
// Modernizr.testAllProps('boxSizing')
Modernizr.testAllProps = testPropsAll;
/*>>testallprops*/
/*>>teststyles*/
// Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards
// Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... })
Modernizr.testStyles = injectElementWithStyles;
/*>>teststyles*/
/*>>prefixed*/
// Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input
// Modernizr.prefixed('boxSizing') // 'MozBoxSizing'
// Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style.
// Return values will also be the camelCase variant, if you need to translate that to hypenated style use:
//
// str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
// If you're trying to ascertain which transition end event to bind to, you might do something like...
//
// var transEndEventNames = {
// 'WebkitTransition' : 'webkitTransitionEnd',
// 'MozTransition' : 'transitionend',
// 'OTransition' : 'oTransitionEnd',
// 'msTransition' : 'MSTransitionEnd',
// 'transition' : 'transitionend'
// },
// transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
Modernizr.prefixed = function(prop, obj, elem){
if(!obj) {
return testPropsAll(prop, 'pfx');
} else {
// Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'
return testPropsAll(prop, obj, elem);
}
};
/*>>prefixed*/
/*>>cssclasses*/
// Remove "no-js" class from element, if it exists:
docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') +
// Add the new classes to the element.
(enableClasses ? ' js ' + classes.join(' ') : '');
/*>>cssclasses*/
return Modernizr;
})(this, this.document);
return PlaneUI;
});