blob: c69fa5e1ba6b9156e8ccda9622febe27a3d5e8fd [file] [log] [blame]
/*
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software" ),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*/
// Base class for widgets that need the following features:
//
// I. HTML prototype loading
//
// This class provides HTML prototype loading for widgets. That is, the widget implementation specifies its HTML portions
// in one continuous HTML snippet, and it optionally provides an object containing selectors into the various parts of the
// HTML snippet. This widget loads the HTML snippet into a jQuery object, and optionally assigns jQuery objects to each of
// the selectors in the optionally provided object.
//
// To use this functionality you can either derive from this class, or you can call its prototype's gtype method.
//
// 1. Widgets deriving from this class should define _htmlProto as part of their prototype declaration. _htmlProto looks like
// this:
//
// _htmlProto: {
// source: string|jQuery object (optional) default: string - The name of the widget
// ui: {
// uiElement1: "#ui-element-1-selector",
// uiElement2: "#ui-element-2-selector",
// ...
// subElement: {
// subElement1: "#sub-element-1-selector",
// subElement2: "#sub-element-2-selector",
// ...
// }
// ...
// }
// }
//
// If neither 'source' nor 'ui' are defined, you must still include an empty _htmlProto key (_htmlProto: {}) to indicate
// that you wish to make use of this feature. This will cause a prototype HTML file named after your widget to be loaded.
// The loaded prototype will be placed into your widget's prototype's _protoHtml.source key.
//
// If 'source' is defined as a string, it is the name of the widget (including namespace). This is the default. If your
// widget's HTML prototype is loaded via AJAX and the name of the AJAX file is different from the name of your widget
// (that is, it is not "<widgetName>.prototype.html", then you should explicitly define 'source' as:
//
// If you wish to load HTML prototypes via AJAX, modify the getProtoPath() function defined below to reflect the directory
// structure holding your widget HTML prototypes.
//
// source: "alternateWidgetName"
//
// If AJAX loading fails, source is set to a jQuery object containing a div with an error message. You can check whether
// loading failed via the jQuery object's jqmData( "tizen.widgetex.ajax.fail" ) data item. If false, then the jQuery object
// is the actual prototype loaded via AJAX or present inline. Otherwise, the jQuery object is the error message div.
//
// If 'source' is defined as a jQuery object, it is considered already loaded.
//
// if 'ui' is defined inside _htmlProto, It is assumed to be an object such that every one of its keys is either a string,
// or another object with the same properties as itself.
//
// When a widget is instantiated, the HTML prototype is loaded if not already present in the prototype. If 'ui' is present
// inside _htmlProto, the prototype is cloned. Then, a new structure is created based on 'ui' with each selector replaced
// by a jQuery object containing the results of performing .find() on the prototype's clone with the filter set to the
// value of the string. In the special case where the selector starts with a '#', the ID is removed from the element after
// it is assigned into the structure being created. This structure is then made accessible from the widget instance via
// the '_ui' key (i.e., this._ui).
//
// 2. Use the loadPrototype method when your widget does not derive from $.tizen.widgetex:
// Add _htmlProto to your widget's prototype as described above. Then, in your widget's _create() method, call
// loadPrototype in the following manner:
//
// $.tizen.widgetex.loadPrototype.call(this, "namespace.widgetName" );
//
// Thereafter, you may use the HTML prototype from your widget's prototype or, if you have specified a 'ui' key in your
// _htmlProto key, you may use this._ui from your widget instance.
//
// II. realize method
//
// When a widget is created, some of its properties cannot be set immediately, because they depend on the widths/heights
// of its constituent elements. They can only be calculated when the page containing the widget is made visible via the
// "pageshow" event, because widths/heights always evaluate to 0 when retrieved from a widget that is not visible. When
// you inherit from widgetex, you can add a "_realize" function to your prototype. This function will be called once right
// after _create() if the element that anchors your widget is on a visible page. Otherwise, it will be called when the
// page to which the widget belongs emits the "pageshow" event.
//
// NB: If your widget is inside a container which is itself not visible, such as an expandable or a collapsible, your
// widget will remain hidden even though "pageshow" is fired and therefore _realize is called. In this case, widths and
// heights will be unreliable even during _realize.
//
// III. systematic option handling
//
// If a widget has lots of options, the _setOption function can become a long switch for setting each recognized option.
// It is also tempting to allow options to determine the way a widget is created, by basing decisions on various options
// during _create(). Often, the actions based on option values in _create() are the same as those in _setOption. To avoid
// such code duplication, this class calls _setOption once for each option after _create() has completed.
//
// Furthermore, to avoid writing long switches in a widget's _setOption method, this class implements _setOption in such
// a way that, for any given option (e.g. "myOption" ), _setOption looks for a method _setMyOption in the widget's
// implementation, and if found, calls the method with the value of the option.
//
// If your widget does not inherit from widgetex, you can still use widgetex' systematic option handling:
// 1. define the _setOption method for your widget as follows:
// _setOption: $.tizen.widgetex.prototype._setOption
// 2. Call this._setOptions(this.options) from your widget's _create() function.
// 3. As with widgetex-derived widgets, implement a corresponding _setMyOptionName function for each option myOptionName
// you wish to handle.
//
// IV. systematic value handling for input elements
//
// If your widget happens to be constructed from an <input> element, you have to handle the "value" attribute specially,
// and you have to emit the "change" signal whenever it changes, in addition to your widget's normal signals and option
// changes. With widgetex, you can assign one of your widget's "data-*" properties to be synchronized to the "value"
// property whenever your widget is constructed onto an <input> element. To do this, define, in your prototype:
//
// _value: {
// attr: "data-my-attribute",
// signal: "signal-to-emit"
// }
//
// Then, call this._setValue(newValue) whenever you wish to set the value for your widget. This will set the data-*
// attribute, emit the custom signal (if set) with the new value as its parameter, and, if the widget is based on an
// <input> element, it will also set the "value" attribute and emit the "change" signal.
//
// "attr" is required if you choose to define "_value", and identifies the data-attribute to set in addition to "value",
// if your widget's element is an input.
// "signal" is optional, and will be emitted when setting the data-attribute via this._setValue(newValue).
//
// If your widget does not derive from widgetex, you can still define "_value" as described above and call
// $.tizen.widgetex.setValue(widget, newValue).
//
// V. Systematic enabled/disabled handling for input elements
//
// widgetex implements _setDisabled which will disable the input associated with this widget, if any. Thus, if you derive
// from widgetex and you plan on implementing the disabled state, you should chain up to
// $.tizen.widgetex.prototype._setDisabled(value), rather than $.Widget.prototype._setOption( "disabled", value).
(function ($, undefined) {
// Framework-specific HTML prototype path for AJAX loads
function getProtoPath() {
var theScriptTag = $( "script[data-framework-version][data-framework-root][data-framework-theme]" );
return (theScriptTag.attr( "data-framework-root" ) + "/" +
theScriptTag.attr( "data-framework-version" ) + "/themes/" +
theScriptTag.attr( "data-framework-theme" ) + "/proto-html" );
}
$.widget( "tizen.widgetex", $.mobile.widget, {
_createWidget: function () {
$.tizen.widgetex.loadPrototype.call( this, this.namespace + "." + this.widgetName );
$.mobile.widget.prototype._createWidget.apply( this, arguments );
},
_init: function () {
// TODO THIS IS TEMPORARY PATCH TO AVOID CTXPOPUP PAGE CRASH
if ( this.element === undefined ) {
return;
}
var page = this.element.closest( ".ui-page" ),
self = this,
myOptions = {};
if ( page.is( ":visible" ) ) {
this._realize();
} else {
page.bind( "pageshow", function () { self._realize(); } );
}
$.extend( myOptions, this.options );
this.options = {};
this._setOptions( myOptions );
},
_getCreateOptions: function () {
// if we're dealing with an <input> element, value takes precedence over corresponding data-* attribute, if a
// mapping has been established via this._value. So, assign the value to the data-* attribute, so that it may
// then be assigned to this.options in the superclass' _getCreateOptions
if (this.element.is( "input" ) && this._value !== undefined) {
var theValue =
( ( this.element.attr( "type" ) === "checkbox" || this.element.attr( "type" ) === "radio" )
? this.element.is( ":checked" )
: this.element.is( "[value]" )
? this.element.attr( "value" )
: undefined);
if ( theValue != undefined ) {
this.element.attr( this._value.attr, theValue );
}
}
return $.mobile.widget.prototype._getCreateOptions.apply( this, arguments );
},
_setOption: function ( key, value ) {
var setter = "_set" + key.replace(/^[a-z]/, function (c) { return c.toUpperCase(); } );
if ( this[setter] !== undefined ) {
this[setter]( value );
} else {
$.mobile.widget.prototype._setOption.apply( this, arguments );
}
},
_setDisabled: function ( value ) {
$.Widget.prototype._setOption.call( this, "disabled", value );
if ( this.element.is( "input" ) ) {
this.element.attr( "disabled", value );
}
},
_setValue: function ( newValue ) {
$.tizen.widgetex.setValue( this, newValue );
},
_realize: function () {}
} );
$.tizen.widgetex.setValue = function ( widget, newValue ) {
if ( widget._value !== undefined ) {
var valueString = ( widget._value.makeString ? widget._value.makeString(newValue) : newValue ),
inputType;
widget.element.attr( widget._value.attr, valueString );
if ( widget._value.signal !== undefined ) {
widget.element.triggerHandler( widget._value.signal, newValue );
}
if ( widget.element.is( "input" ) ) {
inputType = widget.element.attr( "type" );
// Special handling for checkboxes and radio buttons, where the presence of the "checked" attribute is really
// the value
if ( inputType === "checkbox" || inputType === "radio" ) {
if ( newValue ) {
widget.element.attr( "checked", true );
} else {
widget.element.removeAttr( "checked" );
}
} else {
widget.element.attr( "value", valueString );
}
widget.element.trigger( "change" );
}
}
};
$.tizen.widgetex.assignElements = function (proto, obj) {
var ret = {},
key;
for ( key in obj ) {
if ( ( typeof obj[key] ) === "string" ) {
ret[key] = proto.find( obj[key] );
if ( obj[key].match(/^#/) ) {
ret[key].removeAttr( "id" );
}
} else {
if ( (typeof obj[key]) === "object" ) {
ret[key] = $.tizen.widgetex.assignElements( proto, obj[key] );
}
}
}
return ret;
};
$.tizen.widgetex.loadPrototype = function ( widget, ui ) {
var ar = widget.split( "." ),
namespace,
widgetName,
htmlProto,
protoPath;
if ( ar.length == 2 ) {
namespace = ar[0];
widgetName = ar[1];
htmlProto = $( "<div></div>" )
.text( "Failed to load proto for widget " + namespace + "." + widgetName + "!" )
.css( {background: "red", color: "blue", border: "1px solid black"} )
.jqmData( "tizen.widgetex.ajax.fail", true );
// If htmlProto is defined
if ( $[namespace][widgetName].prototype._htmlProto !== undefined ) {
// If no source is defined, use the widget name
if ( $[namespace][widgetName].prototype._htmlProto.source === undefined ) {
$[namespace][widgetName].prototype._htmlProto.source = widgetName;
}
// Load the HTML prototype via AJAX if not defined inline
if ( typeof $[namespace][widgetName].prototype._htmlProto.source === "string" ) {
// Establish the path for the proto file
widget = $[namespace][widgetName].prototype._htmlProto.source;
protoPath = getProtoPath();
// Make the AJAX call
$.ajax( {
url: protoPath + "/" + widget + ".prototype.html",
async: false,
dataType: "html"
}).success( function (data, textStatus, jqXHR ) {
htmlProto = $( "<div></div>" ).html(data).jqmData( "tizen.widgetex.ajax.fail", false );
} );
// Assign the HTML proto to the widget prototype
$[namespace][widgetName].prototype._htmlProto.source = htmlProto;
} else { // Otherwise, use the inline definition
// AJAX loading has trivially succeeded, since there was no AJAX loading at all
$[namespace][widgetName].prototype._htmlProto.source.jqmData( "tizen.widgetex.ajax.fail", false );
htmlProto = $[namespace][widgetName].prototype._htmlProto.source;
}
// If there's a "ui" portion in the HTML proto, copy it over to this instance, and
// replace the selectors with the selected elements from a copy of the HTML prototype
if ( $[namespace][widgetName].prototype._htmlProto.ui !== undefined ) {
// Assign the relevant parts of the proto
$.extend( this, {
_ui: $.tizen.widgetex.assignElements( htmlProto.clone(), $[namespace][widgetName].prototype._htmlProto.ui )
});
}
}
}
};
}( jQuery ) );
/*
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software" ),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*/
(function ( $, undefined ) {
$.widget( "tizen.colorwidget", $.tizen.widgetex, {
options: {
color: "#ff0972"
},
_value: {
attr: "data-" + ( $.mobile.ns || "" ) + "color",
signal: "colorchanged"
},
_getElementColor: function ( el, cssProp ) {
return el.jqmData( "clr" );
},
_setElementColor: function ( el, hsl, cssProp ) {
var clrlib = $.tizen.colorwidget.clrlib,
clr = clrlib.RGBToHTML( clrlib.HSLToRGB( hsl ) ),
dclr = clrlib.RGBToHTML( clrlib.HSLToGray( hsl ) );
el.jqmData( "clr", clr );
el.jqmData( "dclr", dclr );
el.jqmData( "cssProp", cssProp );
el.attr( "data-" + ( $.mobile.ns || "" ) + "has-dclr", true );
el.css( cssProp, this.options.disabled ? dclr : clr );
return { clr: clr, dclr: dclr };
},
_displayDisabledState: function ( toplevel ) {
var self = this,
sel = ":jqmData(has-dclr='true')",
dst = toplevel.is( sel ) ? toplevel : $([]),
el;
dst.add( toplevel.find( sel ) )
.each( function () {
el = $( this );
el.css( el.jqmData( "cssProp" ), el.jqmData( self.options.disabled ? "dclr" : "clr" ) );
} );
},
_setColor: function ( value ) {
var currentValue = ( this.options.color );
value = value.match(/#[0-9A-Fa-f]{6}/)
? value
: currentValue.match(/#[0-9A-Fa-f]{6}/)
? currentValue
: $.tizen.colorwidget.prototype.options.color;
if ( this.options.color !== value ) {
this.options.color = value;
this._setValue( value );
return true;
}
return false;
}
} );
$.tizen.colorwidget.clrlib = {
nearestInt: function ( val ) {
var theFloor = Math.floor( val );
return ( ( ( val - theFloor ) > 0.5 ) ? ( theFloor + 1 ) : theFloor );
},
// Converts html color string to rgb array.
//
// Input: string clr_str, where
// clr_str is of the form "#aabbcc"
//
// Returns: [ r, g, b ], where
// r is in [0, 1]
// g is in [0, 1]
// b is in [0, 1]
HTMLToRGB: function ( clr_str ) {
clr_str = ( ( '#' == clr_str.charAt( 0 ) ) ? clr_str.substring( 1 ) : clr_str );
return [ parseInt(clr_str.substring(0, 2), 16) / 255.0,
parseInt(clr_str.substring(2, 4), 16) / 255.0,
parseInt(clr_str.substring(4, 6), 16) / 255.0 ];
},
// Converts rgb array to html color string.
//
// Input: [ r, g, b ], where
// r is in [0, 1]
// g is in [0, 1]
// b is in [0, 1]
//
// Returns: string of the form "#aabbcc"
RGBToHTML: function ( rgb ) {
var ret = "#", val, theFloor,
Nix;
for ( Nix in rgb ) {
val = rgb[Nix] * 255;
theFloor = Math.floor( val );
val = ( ( val - theFloor > 0.5 ) ? ( theFloor + 1 ) : theFloor );
ret = ret + ( ( ( val < 16 ) ? "0" : "" ) + ( val & 0xff ).toString( 16 ) );
}
return ret;
},
// Converts hsl to rgb.
//
// From http://130.113.54.154/~monger/hsl-rgb.html
//
// Input: [ h, s, l ], where
// h is in [0, 360]
// s is in [0, 1]
// l is in [0, 1]
//
// Returns: [ r, g, b ], where
// r is in [0, 1]
// g is in [0, 1]
// b is in [0, 1]
HSLToRGB: function ( hsl ) {
var h = hsl[0] / 360.0, s = hsl[1], l = hsl[2],
temp1,
temp2,
temp3,
ret;
if ( 0 === s ) {
return [ l, l, l ];
}
temp2 = ( ( l < 0.5 )
? l * ( 1.0 + s )
: l + s - l * s);
temp1 = 2.0 * l - temp2;
temp3 = {
r: h + 1.0 / 3.0,
g: h,
b: h - 1.0 / 3.0
};
temp3.r = ( ( temp3.r < 0 ) ? ( temp3.r + 1.0 ) : ( ( temp3.r > 1 ) ? ( temp3.r - 1.0 ) : temp3.r ) );
temp3.g = ( ( temp3.g < 0 ) ? ( temp3.g + 1.0 ) : ( ( temp3.g > 1 ) ? ( temp3.g - 1.0 ) : temp3.g ) );
temp3.b = ( ( temp3.b < 0 ) ? ( temp3.b + 1.0 ) : ( ( temp3.b > 1 ) ? ( temp3.b - 1.0 ) : temp3.b ) );
ret = [( ( ( 6.0 * temp3.r ) < 1 ) ? ( temp1 + ( temp2 - temp1 ) * 6.0 * temp3.r ) :
( ( ( 2.0 * temp3.r ) < 1 ) ? temp2 :
( ( ( 3.0 * temp3.r ) < 2 ) ? ( temp1 + ( temp2 - temp1 ) * ( ( 2.0 / 3.0 ) - temp3.r ) * 6.0 ) :
temp1) ) ),
( ( ( 6.0 * temp3.g ) < 1) ? ( temp1 + ( temp2 - temp1 ) * 6.0 * temp3.g ) :
( ( ( 2.0 * temp3.g ) < 1 ) ? temp2 :
( ( ( 3.0 * temp3.g ) < 2 ) ? ( temp1 + ( temp2 - temp1 ) * ( ( 2.0 / 3.0 ) - temp3.g ) * 6.0 ) :
temp1 ) ) ),
( ( ( 6.0 * temp3.b ) < 1 ) ? ( temp1 + ( temp2 - temp1 ) * 6.0 * temp3.b ) :
( ( ( 2.0 * temp3.b ) < 1 ) ? temp2 :
( ( ( 3.0 * temp3.b ) < 2 ) ? ( temp1 + ( temp2 - temp1 ) * ( ( 2.0 / 3.0 ) - temp3.b ) * 6.0 ) :
temp1 ) ) )];
return ret;
},
// Converts hsv to rgb.
//
// Input: [ h, s, v ], where
// h is in [0, 360]
// s is in [0, 1]
// v is in [0, 1]
//
// Returns: [ r, g, b ], where
// r is in [0, 1]
// g is in [0, 1]
// b is in [0, 1]
HSVToRGB: function ( hsv ) {
return $.tizen.colorwidget.clrlib.HSLToRGB( $.tizen.colorwidget.clrlib.HSVToHSL( hsv ) );
},
// Converts rgb to hsv.
//
// from http://coecsl.ece.illinois.edu/ge423/spring05/group8/FinalProject/HSV_writeup.pdf
//
// Input: [ r, g, b ], where
// r is in [0, 1]
// g is in [0, 1]
// b is in [0, 1]
//
// Returns: [ h, s, v ], where
// h is in [0, 360]
// s is in [0, 1]
// v is in [0, 1]
RGBToHSV: function ( rgb ) {
var min, max, delta, h, s, v, r = rgb[0], g = rgb[1], b = rgb[2];
min = Math.min( r, Math.min( g, b ) );
max = Math.max( r, Math.max( g, b ) );
delta = max - min;
h = 0;
s = 0;
v = max;
if ( delta > 0.00001 ) {
s = delta / max;
if ( r === max ) {
h = ( g - b ) / delta;
} else {
if ( g === max ) {
h = 2 + ( b - r ) / delta;
} else {
h = 4 + ( r - g ) / delta;
}
}
h *= 60;
if ( h < 0 ) {
h += 360;
}
}
return [h, s, v];
},
// Converts hsv to hsl.
//
// Input: [ h, s, v ], where
// h is in [0, 360]
// s is in [0, 1]
// v is in [0, 1]
//
// Returns: [ h, s, l ], where
// h is in [0, 360]
// s is in [0, 1]
// l is in [0, 1]
HSVToHSL: function ( hsv ) {
var max = hsv[2],
delta = hsv[1] * max,
min = max - delta,
sum = max + min,
half_sum = sum / 2,
s_divisor = ( ( half_sum < 0.5 ) ? sum : ( 2 - max - min ) );
return [ hsv[0], ( ( 0 == s_divisor ) ? 0 : ( delta / s_divisor ) ), half_sum ];
},
// Converts rgb to hsl
//
// Input: [ r, g, b ], where
// r is in [0, 1]
// g is in [0, 1]
// b is in [0, 1]
//
// Returns: [ h, s, l ], where
// h is in [0, 360]
// s is in [0, 1]
// l is in [0, 1]
RGBToHSL: function ( rgb ) {
return $.tizen.colorwidget.clrlib.HSVToHSL( $.tizen.colorwidget.clrlib.RGBToHSV( rgb ) );
},
// Converts hsl to grayscale
// Full-saturation magic grayscale values were taken from the Gimp
//
// Input: [ h, s, l ], where
// h is in [0, 360]
// s is in [0, 1]
// l is in [0, 1]
//
// Returns: [ r, g, b ], where
// r is in [0, 1]
// g is in [0, 1]
// b is in [0, 1]
HSLToGray: function ( hsl ) {
var intrinsic_vals = [0.211764706, 0.929411765, 0.71372549, 0.788235294, 0.070588235, 0.28627451, 0.211764706],
idx = Math.floor(hsl[0] / 60),
lowerHalfPercent,
upperHalfPercent,
begVal,
endVal,
val;
// Find hue interval
begVal = intrinsic_vals[idx];
endVal = intrinsic_vals[idx + 1];
// Adjust for lum
if ( hsl[2] < 0.5 ) {
lowerHalfPercent = hsl[2] * 2;
begVal *= lowerHalfPercent;
endVal *= lowerHalfPercent;
} else {
upperHalfPercent = ( hsl[2] - 0.5 ) * 2;
begVal += ( 1.0 - begVal ) * upperHalfPercent;
endVal += ( 1.0 - endVal ) * upperHalfPercent;
}
// This is the gray value at full sat, whereas hsl[2] is the gray value at 0 sat.
val = begVal + ( ( endVal - begVal ) * ( hsl[0] - ( idx * 60 ) ) ) / 60;
// Get value at hsl[1]
val = val + ( hsl[2] - val ) * ( 1.0 - hsl[1] );
return [val, val, val];
}
};
}( jQuery ));
(function ( $, undefined ) {
$.widget( "tizen.huegradient", $.tizen.widgetex, {
_create: function () {
this.element.addClass( "tizen-huegradient" );
},
// Crutches for IE: it is incapable of multi-stop gradients, so add multiple divs inside the given div, each with a
// two-point gradient
_IEGradient: function ( div, disabled ) {
var rainbow = disabled
? ["#363636", "#ededed", "#b6b6b6", "#c9c9c9", "#121212", "#494949", "#363636"]
: ["#ff0000", "#ffff00", "#00ff00", "#00ffff", "#0000ff", "#ff00ff", "#ff0000"],
Nix;
for (Nix = 0 ; Nix < 6 ; Nix++ ) {
$( "<div></div>" )
.css( {
position: "absolute",
width: ( 100 / 6 ) + "%",
height: "100%",
left: ( Nix * 100 / 6 ) + "%",
top: "0px",
filter: "progid:DXImageTransform.Microsoft.gradient (startColorstr='" + rainbow[Nix] + "', endColorstr='" + rainbow[Nix + 1] + "', GradientType = 1)"
} )
.appendTo( div );
}
},
_setDisabled: function ( value ) {
$.Widget.prototype._setOption.call( this, "disabled", value );
if ( $.mobile.browser.ie ) {
this._IEGradient( this.element.empty(), value );
}
}
} );
}( jQuery ) );
( function ( $, undefined ) {
$.widget( "todons.colorwidget", $.mobile.widget, {
options: {
color: "#ff0972"
},
_create: function () {
$.extend ( this, {
isInput: this.element.is( "input" )
} );
/* "value", if present, takes precedence over "data-color" */
if ( this.isInput ) {
if ( this.element.attr( "value" ).match(/#[0-9A-Fa-f]{6}/) ) {
this.element.attr( "data-color", this.element.attr( "value" ) );
}
}
$.mobile.todons.parseOptions( this, true );
},
_setOption: function ( key, value, unconditional ) {
if ( undefined === unconditional ) {
unconditional = false;
}
if ( key === "color" ) {
this._setColor(value, unconditional);
}
},
_setColor: function ( value, unconditional ) {
if ( value.match(/#[0-9A-Fa-f]{6}/) && ( value != this.options.color || unconditional ) ) {
this.options.color = value;
this.element.attr( "data-color", value );
if ( this.isInput ) {
this.element.attr( "value", value );
}
this.element.triggerHandler( "colorchanged", value );
return true;
}
return false;
}
} );
}( jQuery ) );
/*
* jQuery Mobile Widget @VERSION - listview autodividers
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (c) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Elliot Smith <elliot.smith@intel.com>
*/
// Applies dividers automatically to a listview, using link text
// (for link lists) or text (for readonly lists) as the basis for the
// divider text.
//
// Apply using autodividers({type: 'X'}) on a <ul> with
// data-role="listview", or with data-autodividers="true", where X
// is the type of divider to create. The default divider type is 'alpha',
// meaning first characters of list item text, upper-cased.
//
// The element used to derive the text for the auto dividers defaults
// to the first link inside the li; failing that, the text directly inside
// the li element is used. This can be overridden with the
// data-autodividers-selector attribute or via options; the selector
// will use each li element as its context.
//
// Any time a new li element is added to the list, or an li element is
// removed, this extension will update the dividers in the listview
// accordingly.
//
// Note that if a listview already has dividers, applying this
// extension will remove all the existing dividers and replace them
// with new, generated ones.
//
// Also note that this extension doesn't sort the list: it only creates
// dividers based on text inside list items. So if your list isn't
// alphabetically-sorted, you may get duplicate dividers.
//
// So, for example, this markup:
//
// <ul id="has-no-dividers" data-role="listview" data-autodividers="alpha">
// <li>Barry</li>
// <li>Carrie</li>
// <li>Betty</li>
// <li>Harry</li>
// <li>Carly</li>
// <li>Hetty</li>
// </ul>
//
// will produce dividers like this:
//
// <ul data-role="listview" data-autodividers="alpha">
// <li data-role="list-divider">B</li>
// <li>Barry</li>
// <li data-role="list-divider">C</li>
// <li>Carrie</li>
// <li data-role="list-divider">B</li>
// <li>Betty</li>
// <li data-role="list-divider">H</li>
// <li>Harry</li>
// <li data-role="list-divider">C</li>
// <li>Carly</li>
// <li data-role="list-divider">H</li>
// <li>Hetty</li>
// </ul>
//
// with each divider occuring twice.
//
// Options:
//
// selector: The jQuery selector to use to find text for the
// generated dividers. Default is to use the first 'a'
// (link) element. If this selector doesn't find any
// text, the widget automatically falls back to the text
// inside the li (for read-only lists). Can be set to a custom
// selector via data-autodividers-selector="..." or the 'selector'
// option.
//
// type: 'alpha' (default) sets the auto divider type to "uppercased
// first character of text selected from each item"; "full" sets
// it to the unmodified text selected from each item. Set via
// the data-autodividers="<type>" attribute on the listview or
// the 'type' option.
//
// Events:
//
// updatelayout: Triggered if the dividers in the list change;
// this happens if list items are added to the listview,
// which causes the autodividers to be regenerated.
(function ( $, undefined ) {
var autodividers = function ( options ) {
var list = $( this ),
listview = list.data( 'listview' ),
dividerType,
textSelector,
getDividerText,
mergeDividers,
isNonDividerLi,
liAdded,
liRemoved;
options = options || {};
dividerType = options.type || list.jqmData( 'autodividers' ) || 'alpha';
textSelector = options.selector || list.jqmData( 'autodividers-selector' ) || 'a';
getDividerText = function ( elt ) {
// look for some text in the item
var text = elt.find( textSelector ).text() || elt.text() || null;
if ( !text ) {
return null;
}
// create the text for the divider
if ( dividerType === 'alpha' ) {
text = text.slice( 0, 1 ).toUpperCase();
}
return text;
};
mergeDividers = function () {
var dividersChanged = false,
divider,
dividerText,
selector,
nextDividers;
// any dividers which are following siblings of a divider, where
// there are no dividers with different text inbetween, can be removed
list.find( 'li.ui-li-divider' ).each(function () {
divider = $( this );
dividerText = divider.text();
selector = '.ui-li-divider:not(:contains(' + dividerText + '))';
nextDividers = divider.nextUntil( selector );
nextDividers = nextDividers.filter( '.ui-li-divider:contains(' + dividerText + ')' );
if ( nextDividers.length > 0 ) {
nextDividers.remove();
dividersChanged = true;
}
} );
if ( dividersChanged ) {
list.trigger( 'updatelayout' );
}
};
// check that elt is a non-divider li element
isNonDividerLi = function ( elt ) {
return elt.is('li') &&
elt.jqmData( 'role' ) !== 'list-divider';
};
// li element inserted, so check whether it needs a divider
liAdded = function ( li ) {
var dividerText = getDividerText( li ),
existingDividers,
divider;
if ( !dividerText ) {
listview.refresh();
return;
}
// add expected divider for this li if it doesn't exist
existingDividers = li.prevAll( '.ui-li-divider:first:contains(' + dividerText + ')' );
if ( existingDividers.length === 0 ) {
divider = $( '<li>' + dividerText + '</li>' );
divider.attr( 'data-' + $.mobile.ns + 'role', 'list-divider' );
li.before( divider );
listview.refresh();
mergeDividers();
} else {
listview.refresh();
}
};
// li element removed, so check whether its divider should go
liRemoved = function ( li ) {
var dividerText = getDividerText( li ),
precedingItems,
nextItems;
if ( !dividerText ) {
listview.refresh();
return;
}
// remove divider for this li if there are no other
// li items for the divider before or after this li item
precedingItems = li.prevUntil( '.ui-li-divider:contains(' + dividerText + ')' );
nextItems = li.nextUntil( '.ui-li-divider' );
if ( precedingItems.length === 0 && nextItems.length === 0 ) {
li.prevAll( '.ui-li-divider:contains(' + dividerText + '):first' ).remove();
listview.refresh();
mergeDividers();
} else {
listview.refresh();
}
};
// set up the dividers on first create
list.find( 'li' ).each( function () {
var li = $( this );
// remove existing dividers
if ( li.jqmData( 'role' ) === 'list-divider' ) {
li.remove();
} else { // make new dividers for list items
liAdded( li );
}
} );
// bind to DOM events to keep list up to date
list.bind( 'DOMNodeInserted', function ( e ) {
var elt = $( e.target );
if ( !isNonDividerLi( elt ) ) {
return;
}
liAdded( elt );
} );
list.bind( 'DOMNodeRemoved', function ( e ) {
var elt = $( e.target );
if ( !isNonDividerLi( elt ) ) {
return;
}
liRemoved( elt );
} );
};
$.fn.autodividers = autodividers;
$( ":jqmData(role=listview)" ).live( "listviewcreate", function () {
var list = $( this );
if ( list.is( ':jqmData(autodividers)' ) ) {
list.autodividers();
}
} );
}( jQuery ) );
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software" ),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*/
// most of following codes are derived from jquery.mobile.scrollview.js
(function ( $, window, document, undefined ) {
function circularNum( num, total ) {
var n = num % total;
if ( n < 0 ) {
n = total + n;
}
return n;
}
function setElementTransform( $ele, x, y ) {
var v = "translate3d( " + x + "," + y + ", 0px)";
$ele.css({
"-moz-transform": v,
"-webkit-transform": v,
"transform": v
} );
}
function MomentumTracker( options ) {
this.options = $.extend( {}, options );
this.easing = "easeOutQuad";
this.reset();
}
var tstates = {
scrolling : 0,
done : 1
};
function getCurrentTime() {
return ( new Date()).getTime();
}
$.extend( MomentumTracker.prototype, {
start: function ( pos, speed, duration ) {
this.state = ( speed != 0 ) ? tstates.scrolling : tstates.done;
this.pos = pos;
this.speed = speed;
this.duration = duration;
this.fromPos = 0;
this.toPos = 0;
this.startTime = getCurrentTime();
},
reset: function () {
this.state = tstates.done;
this.pos = 0;
this.speed = 0;
this.duration = 0;
},
update: function () {
var state = this.state,
duration,
elapsed,
dx,
x;
if ( state == tstates.done ) {
return this.pos;
}
duration = this.duration;
elapsed = getCurrentTime() - this.startTime;
elapsed = elapsed > duration ? duration : elapsed;
dx = this.speed * ( 1 - $.easing[this.easing](elapsed / duration, elapsed, 0, 1, duration ) );
x = this.pos + dx;
this.pos = x;
if ( elapsed >= duration ) {
this.state = tstates.done;
}
return this.pos;
},
done: function () {
return this.state == tstates.done;
},
getPosition: function () {
return this.pos;
}
} );
jQuery.widget( "mobile.circularview", jQuery.mobile.widget, {
options: {
fps: 60,
scrollDuration: 2000,
moveThreshold: 10,
moveIntervalThreshold: 150,
startEventName: "scrollstart",
updateEventName: "scrollupdate",
stopEventName: "scrollstop",
eventType: $.support.touch ? "touch" : "mouse",
delayedClickSelector: "a, .ui-btn",
delayedClickEnabled: false
},
_makePositioned: function ( $ele ) {
if ( $ele.css( 'position' ) == 'static' ) {
$ele.css( 'position', 'relative' );
}
},
_create: function () {
this._$clip = $( this.element).addClass( "ui-scrollview-clip" );
var $child = this._$clip.children(),
self;
//if ( $child.length > 1 ) {
$child = this._$clip.wrapInner( "<div></div>" ).children();
//}
this._$view = $child.addClass( "ui-scrollview-view" );
this._$list = $child.children();
this._$clip.css( "overflow", "hidden" );
this._makePositioned( this._$clip );
this._$view.css( "overflow", "hidden" );
this._tracker = new MomentumTracker( this.options );
this._timerInterval = 1000 / this.options.fps;
this._timerID = 0;
self = this;
this._timerCB = function () { self._handleMomentumScroll(); };
this.refresh();
this._addBehaviors();
},
refresh: function () {
var itemsPerView;
this._viewWidth = this._$view.width();
this._clipWidth = $( window ).width();
this._itemWidth = this._$list.children().first().outerWidth();
this._$items = this._$list.children().detach();
itemsPerView = this._clipWidth / this._itemWidth;
itemsPerView = Math.ceil( itemsPerView * 10 ) / 10;
this._itemsPerView = parseInt( itemsPerView, 10 );
this._rx = -this._itemWidth;
this._sx = -this._itemWidth;
this._setItems();
},
_startMScroll: function ( speedX, speedY ) {
this._stopMScroll();
var keepGoing = false,
duration = this.options.scrollDuration,
t = this._tracker,
c = this._clipWidth,
v = this._viewWidth;
this._$clip.trigger( this.options.startEventName);
t.start( this._rx, speedX, duration, (v > c ) ? -(v - c) : 0, 0 );
keepGoing = !t.done();
if ( keepGoing ) {
this._timerID = setTimeout( this._timerCB, this._timerInterval );
} else {
this._stopMScroll();
}
//console.log( "startmscroll" + this._rx + "," + this._sx );
},
_stopMScroll: function () {
if ( this._timerID ) {
this._$clip.trigger( this.options.stopEventName );
clearTimeout( this._timerID );
}
this._timerID = 0;
if ( this._tracker ) {
this._tracker.reset();
}
//console.log( "stopmscroll" + this._rx + "," + this._sx );
},
_handleMomentumScroll: function () {
var keepGoing = false,
v = this._$view,
x = 0,
y = 0,
t = this._tracker;
if ( t ) {
t.update();
x = t.getPosition();
keepGoing = !t.done();
}
this._setScrollPosition( x, y );
this._rx = x;
this._$clip.trigger( this.options.updateEventName, [ { x: x, y: y } ] );
if ( keepGoing ) {
this._timerID = setTimeout( this._timerCB, this._timerInterval );
} else {
this._stopMScroll();
}
},
_setItems: function () {
var i,
$item;
for ( i = -1; i < this._itemsPerView + 1; i++ ) {
$item = this._$items[ circularNum( i, this._$items.length ) ];
this._$list.append( $item );
}
setElementTransform( this._$view, this._sx + "px", 0 );
this._$view.width( this._itemWidth * ( this._itemsPerView + 2 ) );
this._viewWidth = this._$view.width();
},
_setScrollPosition: function ( x, y ) {
var sx = this._sx,
dx = x - sx,
di = parseInt( dx / this._itemWidth, 10 ),
i,
idx,
$item;
if ( di > 0 ) {
for ( i = 0; i < di; i++ ) {
this._$list.children().last().detach();
idx = -parseInt( ( sx / this._itemWidth ) + i + 3, 10 );
$item = this._$items[ circularNum( idx, this._$items.length ) ];
this._$list.prepend( $item );
//console.log( "di > 0 : " + idx );
}
} else if ( di < 0 ) {
for ( i = 0; i > di; i-- ) {
this._$list.children().first().detach();
idx = this._itemsPerView - parseInt( ( sx / this._itemWidth ) + i, 10 );
$item = this._$items[ circularNum( idx, this._$items.length ) ];
this._$list.append( $item );
//console.log( "di < 0 : " + idx );
}
}
this._sx += di * this._itemWidth;
setElementTransform( this._$view, ( x - this._sx - this._itemWidth ) + "px", 0 );
//console.log( "rx " + this._rx + "sx " + this._sx );
},
_enableTracking: function () {
$(document).bind( this._dragMoveEvt, this._dragMoveCB );
$(document).bind( this._dragStopEvt, this._dragStopCB );
},
_disableTracking: function () {
$(document).unbind( this._dragMoveEvt, this._dragMoveCB );
$(document).unbind( this._dragStopEvt, this._dragStopCB );
},
_getScrollHierarchy: function () {
var svh = [],
d;
this._$clip.parents( '.ui-scrollview-clip' ).each( function () {
d = $( this ).jqmData( 'circulaview' );
if ( d ) {
svh.unshift( d );
}
} );
return svh;
},
centerTo: function ( selector ) {
var i,
newX;
for ( i = 0; i < this._$items.length; i++ ) {
if ( $( this._$items[i]).is( selector ) ) {
newX = -( i * this._itemWidth - this._clipWidth / 2 + this._itemWidth * 2 );
this.scrollTo( newX, 0 );
console.log( i + "," + newX );
return;
}
}
},
scrollTo: function ( x, y, duration ) {
this._stopMScroll();
if ( !duration ) {
this._setScrollPosition( x, y );
this._rx = x;
return;
}
x = -x;
y = -y;
var self = this,
start = getCurrentTime(),
efunc = $.easing.easeOutQuad,
sx = this._rx,
sy = 0,
dx = x - sx,
dy = 0,
tfunc,
elapsed,
ec;
tfunc = function () {
elapsed = getCurrentTime() - start;
if ( elapsed >= duration ) {
self._timerID = 0;
self._setScrollPosition( x, y );
} else {
ec = efunc( elapsed / duration, elapsed, 0, 1, duration );
self._setScrollPosition( sx + ( dx * ec ), sy + ( dy * ec ) );
self._timerID = setTimeout( tfunc, self._timerInterval );
}
};
this._timerID = setTimeout( tfunc, this._timerInterval );
},
getScrollPosition: function () {
return { x: -this._rx, y: 0 };
},
_handleDragStart: function ( e, ex, ey ) {
$.each( this._getScrollHierarchy(), function ( i, sv ) {
sv._stopMScroll();
} );
this._stopMScroll();
if ( this.options.delayedClickEnabled ) {
this._$clickEle = $( e.target ).closest( this.options.delayedClickSelector );
}
this._lastX = ex;
this._lastY = ey;
this._speedX = 0;
this._speedY = 0;
this._didDrag = false;
this._lastMove = 0;
this._enableTracking();
this._ox = ex;
this._nx = this._rx;
if ( this.options.eventType == "mouse" || this.options.delayedClickEnabled ) {
e.preventDefault();
}
//console.log( "scrollstart" + this._rx + "," + this._sx );
e.stopPropagation();
},
_handleDragMove: function ( e, ex, ey ) {
this._lastMove = getCurrentTime();
var dx = ex - this._lastX,
dy = ey - this._lastY;
this._speedX = dx;
this._speedY = 0;
this._didDrag = true;
this._lastX = ex;
this._lastY = ey;
this._mx = ex - this._ox;
this._setScrollPosition( this._nx + this._mx, 0 );
//console.log( "scrollmove" + this._rx + "," + this._sx );
return false;
},
_handleDragStop: function ( e ) {
var l = this._lastMove,
t = getCurrentTime(),
doScroll = l && ( t - l ) <= this.options.moveIntervalThreshold,
sx = ( this._tracker && this._speedX && doScroll ) ? this._speedX : 0,
sy = 0;
this._rx = this._mx ? this._nx + this._mx : this._rx;
if ( sx ) {
this._startMScroll( sx, sy );
}
//console.log( "scrollstop" + this._rx + "," + this._sx );
this._disableTracking();
if ( !this._didDrag && this.options.delayedClickEnabled && this._$clickEle.length ) {
this._$clickEle
.trigger( "mousedown" )
.trigger( "mouseup" )
.trigger( "click" );
}
if ( this._didDrag ) {
e.preventDefault();
e.stopPropagation();
}
return this._didDrag ? false : undefined;
},
_addBehaviors: function () {
var self = this;
if ( this.options.eventType === "mouse" ) {
this._dragStartEvt = "mousedown";
this._dragStartCB = function ( e ) {
return self._handleDragStart( e, e.clientX, e.clientY );
};
this._dragMoveEvt = "mousemove";
this._dragMoveCB = function ( e ) {
return self._handleDragMove( e, e.clientX, e.clientY );
};
this._dragStopEvt = "mouseup";
this._dragStopCB = function ( e ) {
return self._handleDragStop( e );
};
this._$view.bind( "vclick", function (e) {
return !self._didDrag;
} );
} else { //touch
this._dragStartEvt = "touchstart";
this._dragStartCB = function ( e ) {
var t = e.originalEvent.targetTouches[0];
return self._handleDragStart(e, t.pageX, t.pageY );
};
this._dragMoveEvt = "touchmove";
this._dragMoveCB = function ( e ) {
var t = e.originalEvent.targetTouches[0];
return self._handleDragMove(e, t.pageX, t.pageY );
};
this._dragStopEvt = "touchend";
this._dragStopCB = function ( e ) {
return self._handleDragStop( e );
};
}
this._$view.bind( this._dragStartEvt, this._dragStartCB );
}
} );
$( document ).bind( "pagecreate create", function ( e ) {
$( $.mobile.circularview.prototype.options.initSelector, e.target ).circularview();
} );
}( jQuery, window, document ) ); // End Component
/* TBD */
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
* Copyright (c) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Gabriel Schulhof <gabriel.schulhof@intel.com>
*/
// It displays a grid two rows by five columns of colors.
//
// The colors are automatically computed based on the hue
// of the color set by the color attribute (see below).
//
// One of the displayed colors is the color attribute itself
// and the others are multiples of 360/10 away from that color;
// 10 is the total number of colors displayed (2 rows by 5 columns).
//
// To apply, add the attribute data-role="colorpalette" to a <div>
// element inside a page. Alternatively, call colorpalette() on an
// element.
//
// Options:
//
// color: String; initial color can be specified in html
// using the data-color="#ff00ff" attribute or
// when constructed in javascript, eg :
// $("#mycolorpalette").colorpalette({ color: "#ff00ff" });
// where the html might be :
// <div id="mycolorpalette"></div>
// The color can be changed post-construction like this :
// $("#mycolorpalette").colorpalette("option", "color", "#ABCDEF");
// Default: "#1a8039"
/*
* Colorpalette displays a grid two rows by five columns of colors.
*
* The colors are automatically computed based on the hue
* of the color set by the color attribute (see below).
*
* One of the displayed colors is the color attribute itself
* and the others are multiples of 360/10 away from that color;
* 10 is the total number of colors displayed (2 rows by 5 columns).
*
* HTML attributes:
*
* To apply, add the attribute data-role="colorpalette" to a <div>
* element inside a page. Alternatively, call colorpalette() on an
* element.
*
* data-role: Myst have 'colorpalette'.
* data-color: String; initial color can be specified in html
* using the data-color="#ff00ff" attribute or
* when constructed in javascript, eg :
* $("#mycolorpalette").colorpalette({ color: "#ff00ff" });
* where the html might be :
* <div id="mycolorpalette"></div>
* The color can be changed post-construction like this :
* $("#mycolorpalette").colorpalette("option", "color", "#ABCDEF");
* Default: "#1a8039"
*
*APIs:
* $('obj').colorpalette() : Make an object to a colorpalette widget.
*
*Events:
* No event.
*
*Examples:
* <div data-role="colorpalette" data-color: "#ffffff"></div>
*
* <div id="toBeColorpalette"></div>
* <script>
* $("#toBeColorpalette").colorpalette({ color: "#ffffff" });
* </script>
*
*/
( function ( $, undefined ) {
$.widget( "tizen.colorpalette", $.tizen.colorwidget, {
options: {
showPreview: false,
initSelector: ":jqmData(role='colorpalette')"
},
_htmlProto: {
source:
$("<div><div id='colorpalette' class='ui-colorpalette jquery-mobile-ui-widget' data-n-choices='10'>" +
" <div class='colorpalette-preview-container' id='colorpalette-preview-container'>" +
" <div id='colorpalette-preview' class='colorpalette-preview ui-corner-all'></div>" +
" </div>" +
" <div class='colorpalette-table'>" +
" <div class='colorpalette-normal-row'>" +
" <div class='colorpalette-choice-container-left'>" +
" <div data-colorpalette-choice='0' class='colorpalette-choice ui-corner-all'></div>" +
" </div>" +
" <div class='colorpalette-choice-container-rest'>" +
" <div data-colorpalette-choice='1' class='colorpalette-choice ui-corner-all'></div>" +
" </div>" +
" <div class='colorpalette-choice-container-rest'>" +
" <div data-colorpalette-choice='2' class='colorpalette-choice ui-corner-all'></div>" +
" </div>" +
" <div class='colorpalette-choice-container-rest'>" +
" <div data-colorpalette-choice='3' class='colorpalette-choice ui-corner-all'></div>" +
" </div>" +
" <div class='colorpalette-choice-container-rest'>" +
" <div data-colorpalette-choice='4' class='colorpalette-choice ui-corner-all'></div>" +
" </div>" +
" </div>" +
" <div class='colorpalette-bottom-row'>" +
" <div class='colorpalette-choice-container-left'>" +
" <div data-colorpalette-choice='5' class='colorpalette-choice ui-corner-all'></div>" +
" </div>" +
" <div class='colorpalette-choice-container-rest'>" +
" <div data-colorpalette-choice='6' class='colorpalette-choice ui-corner-all'></div>" +
" </div>" +
" <div class='colorpalette-choice-container-rest'>" +
" <div data-colorpalette-choice='7' class='colorpalette-choice ui-corner-all'></div>" +
" </div>" +
" <div class='colorpalette-choice-container-rest'>" +
" <div data-colorpalette-choice='8' class='colorpalette-choice ui-corner-all'></div>" +
" </div>" +
" <div class='colorpalette-choice-container-rest'>" +
" <div data-colorpalette-choice='9' class='colorpalette-choice ui-corner-all'></div>" +
" </div>" +
" </div>" +
" </div>" +
"</div>" +
"</div>")
, ui: {
clrpalette: "#colorpalette",
preview: "#colorpalette-preview",
previewContainer: "#colorpalette-preview-container"
}
},
_create: function () {
var self = this;
this.element
.css( "display", "none" )
.after( this._ui.clrpalette );
this._ui.clrpalette.find( "[data-colorpalette-choice]" ).bind( "vclick", function ( e ) {
var clr = $.tizen.colorwidget.prototype._getElementColor.call(this, $(e.target)),
Nix,
nChoices = self._ui.clrpalette.attr( "data-" + ( $.mobile.ns || "" ) + "n-choices" ),
choiceId,
rgbMatches;
rgbMatches = clr.match(/rgb\(([0-9]*), *([0-9]*), *([0-9]*)\)/);
if ( rgbMatches && rgbMatches.length > 3 ) {
clr = $.tizen.colorwidget.clrlib.RGBToHTML( [
parseInt(rgbMatches[1], 10) / 255,
parseInt(rgbMatches[2], 10) / 255,
parseInt(rgbMatches[3], 10) / 255] );
}
for ( Nix = 0 ; Nix < nChoices ; Nix++ ) {
self._ui.clrpalette.find( "[data-colorpalette-choice=" + Nix + "]" ).removeClass( "colorpalette-choice-active" );
}
$(e.target).addClass( "colorpalette-choice-active" );
$.tizen.colorwidget.prototype._setColor.call( self, clr );
$.tizen.colorwidget.prototype._setElementColor.call( self, self._ui.preview, $.tizen.colorwidget.clrlib.RGBToHSL( $.tizen.colorwidget.clrlib.HTMLToRGB( clr ) ), "background" );
} );
},
_setShowPreview: function ( show ) {
if ( show ) {
this._ui.previewContainer.removeAttr( "style" );
} else {
this._ui.previewContainer.css( "display", "none" );
}
this.element.attr( "data-" + ( $.mobile.ns || "" ) + "show-preview", show );
this.options.showPreview = show;
},
widget: function ( value ) {
return this._ui.clrpalette;
},
_setDisabled: function ( value ) {
$.tizen.widgetex.prototype._setDisabled.call( this, value );
this._ui.clrpalette[value ? "addClass" : "removeClass"]( "ui-disabled" );
$.tizen.colorwidget.prototype._displayDisabledState.call( this, this._ui.clrpalette );
},
_setColor: function ( clr ) {
if ( $.tizen.colorwidget.prototype._setColor.call( this, clr ) ) {
clr = this.options.color;
var Nix,
activeIdx = -1,
nChoices = this._ui.clrpalette.attr( "data-" + ( $.mobile.ns || "" ) + "n-choices" ),
hsl = $.tizen.colorwidget.clrlib.RGBToHSL( $.tizen.colorwidget.clrlib.HTMLToRGB( clr ) ),
origHue = hsl[0],
offset = hsl[0] / 36,
theFloor = Math.floor( offset ),
newClr,
currentlyActive;
$.tizen.colorwidget.prototype._setElementColor.call( this, this._ui.preview,
$.tizen.colorwidget.clrlib.RGBToHSL( $.tizen.colorwidget.clrlib.HTMLToRGB( clr ) ), "background" );
offset = ( offset - theFloor < 0.5 )
? ( offset - theFloor )
: ( offset - ( theFloor + 1 ) );
offset *= 36;
for ( Nix = 0 ; Nix < nChoices ; Nix++ ) {
hsl[0] = Nix * 36 + offset;
hsl[0] = ( ( hsl[0] < 0) ? ( hsl[0] + 360 ) : ( ( hsl[0] > 360 ) ? ( hsl[0] - 360 ) : hsl[0] ) );
if ( hsl[0] === origHue ) {
activeIdx = Nix;
}
newClr = $.tizen.colorwidget.clrlib.RGBToHTML( $.tizen.colorwidget.clrlib.HSLToRGB( hsl ) );
$.tizen.colorwidget.prototype._setElementColor.call( this, this._ui.clrpalette.find( "[data-colorpalette-choice=" + Nix + "]" ),
$.tizen.colorwidget.clrlib.RGBToHSL( $.tizen.colorwidget.clrlib.HTMLToRGB( newClr ) ), "background" );
}
if (activeIdx != -1) {
currentlyActive = parseInt( this._ui.clrpalette.find( ".colorpalette-choice-active" ).attr( "data-" + ($.mobile.ns || "" ) + "colorpalette-choice" ), 10 );
if ( currentlyActive != activeIdx ) {
this._ui.clrpalette.find( "[data-colorpalette-choice=" + currentlyActive + "]" ).removeClass( "colorpalette-choice-active" );
this._ui.clrpalette.find( "[data-colorpalette-choice=" + activeIdx + "]" ).addClass( "colorpalette-choice-active" );
}
}
}
}
});
$( document ).bind( "pagecreate create", function ( e ) {
$( $.tizen.colorpalette.prototype.options.initSelector, e.target )
.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
.colorpalette();
});
}( jQuery ) );
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
* Copyright (c) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Gabriel Schulhof <gabriel.schulhof@intel.com>
*/
// Displays a 2D hue/saturation spectrum and a lightness slider.
//
// To apply, add the attribute data-role="colorpicker" to a <div>
// element inside a page. Alternatively, call colorpicker()
// on an element (see below).
//
//Options:
// color: String; can be specified in html using the
// data-color="#ff00ff" attribute or when constructed
// $("#mycolorpicker").colorpicker({ color: "#ff00ff" });
// where the html might be :
// <div id="mycolorpicker"/>
(function ( $, undefined ) {
$.widget( "tizen.colorpicker", $.tizen.colorwidget, {
options: {
initSelector: ":jqmData(role='colorpicker')"
},
_htmlProto: {
source:
$("<div><div id='colorpicker' class='ui-colorpicker'>" +
" <div class='colorpicker-hs-container'>" +
" <div id='colorpicker-hs-hue-gradient' class='colorpicker-hs-mask'></div>" +
" <div id='colorpicker-hs-sat-gradient' class='colorpicker-hs-mask sat-gradient'></div>" +
" <div id='colorpicker-hs-val-mask' class='colorpicker-hs-mask' data-event-source='hs'></div>" +
" <div id='colorpicker-hs-selector' class='colorpicker-hs-selector ui-corner-all'></div>" +
" </div>" +
" <div class='colorpicker-l-container'>" +
" <div id='colorpicker-l-gradient' class='colorpicker-l-mask l-gradient' data-event-source='l'></div>" +
" <div id='colorpicker-l-selector' class='colorpicker-l-selector ui-corner-all'></div>" +
" </div>" +
" <div style='clear: both;'></div>" +
"</div>" +
"</div>")
, ui: {
clrpicker: "#colorpicker",
hs: {
hueGradient: "#colorpicker-hs-hue-gradient",
gradient: "#colorpicker-hs-sat-gradient",
eventSource: "[data-event-source='hs']",
valMask: "#colorpicker-hs-val-mask",
selector: "#colorpicker-hs-selector"
},
l: {
gradient: "#colorpicker-l-gradient",
eventSource: "[data-event-source='l']",
selector: "#colorpicker-l-selector"
}
}
},
_create: function () {
var self = this;
this.element
.css( "display", "none" )
.after( this._ui.clrpicker );
this._ui.hs.hueGradient.huegradient();
$.extend( self, {
dragging: false,
draggingHS: false,
selectorDraggingOffset: {
x : -1,
y : -1
},
dragging_hsl: undefined
} );
$( document )
.bind( "vmousemove", function ( event ) {
if ( self.dragging ) {
event.stopPropagation();
event.preventDefault();
}
} )
.bind( "vmouseup", function ( event ) {
if ( self.dragging ) {
self.dragging = false;
}
} );
this._bindElements( "hs" );
this._bindElements( "l" );
},
_bindElements: function ( which ) {
var self = this,
stopDragging = function ( event ) {
self.dragging = false;
event.stopPropagation();
event.preventDefault();
};
this._ui[which].eventSource
.bind( "vmousedown mousedown", function ( event ) { self._handleMouseDown( event, which, false ); } )
.bind( "vmousemove" , function ( event ) { self._handleMouseMove( event, which, false ); } )
.bind( "vmouseup" , stopDragging );
this._ui[which].selector
.bind( "vmousedown mousedown", function ( event ) { self._handleMouseDown( event, which, true); } )
.bind( "touchmove vmousemove", function ( event ) { self._handleMouseMove( event, which, true); } )
.bind( "vmouseup" , stopDragging );
},
_handleMouseDown: function ( event, containerStr, isSelector ) {
var coords = $.mobile.tizen.targetRelativeCoordsFromEvent( event ),
widgetStr = isSelector ? "selector" : "eventSource";
if ( ( coords.x >= 0 && coords.x <= this._ui[containerStr][widgetStr].width() &&
coords.y >= 0 && coords.y <= this._ui[containerStr][widgetStr].height() ) || isSelector ) {
this.dragging = true;
this.draggingHS = ( "hs" === containerStr );
if ( isSelector ) {
this.selectorDraggingOffset.x = coords.x;
this.selectorDraggingOffset.y = coords.y;
}
this._handleMouseMove( event, containerStr, isSelector, coords );
}
},
_handleMouseMove: function ( event, containerStr, isSelector, coords ) {
var potential_h,
potential_s,
potential_l;
if ( this.dragging &&
!( ( this.draggingHS && containerStr === "l" ) ||
( !this.draggingHS && containerStr === "hs" ) ) ) {
coords = ( coords || $.mobile.tizen.targetRelativeCoordsFromEvent( event ) );
if ( this.draggingHS ) {
potential_h = isSelector
? this.dragging_hsl[0] / 360 + ( coords.x - this.selectorDraggingOffset.x ) / this._ui[containerStr].eventSource.width()
: coords.x / this._ui[containerStr].eventSource.width();
potential_s = isSelector
? this.dragging_hsl[1] + ( coords.y - this.selectorDraggingOffset.y ) / this._ui[containerStr].eventSource.height()
: coords.y / this._ui[containerStr].eventSource.height();
this.dragging_hsl[0] = Math.min( 1.0, Math.max( 0.0, potential_h ) ) * 360;
this.dragging_hsl[1] = Math.min( 1.0, Math.max( 0.0, potential_s ) );
} else {
potential_l = isSelector
? this.dragging_hsl[2] + ( coords.y - this.selectorDraggingOffset.y ) / this._ui[containerStr].eventSource.height()
: coords.y / this._ui[containerStr].eventSource.height();
this.dragging_hsl[2] = Math.min( 1.0, Math.max( 0.0, potential_l ) );
}
if ( !isSelector ) {
this.selectorDraggingOffset.x = Math.ceil( this._ui[containerStr].selector.outerWidth() / 2.0 );
this.selectorDraggingOffset.y = Math.ceil( this._ui[containerStr].selector.outerHeight() / 2.0 );
}
this._updateSelectors( this.dragging_hsl );
event.stopPropagation();
event.preventDefault();
}
},
_updateSelectors: function ( hsl ) {
var clr = $.tizen.colorwidget.prototype._setElementColor.call( this, this._ui.hs.selector, [hsl[0], 1.0 - hsl[1], hsl[2]], "background" ).clr,
gray = $.tizen.colorwidget.clrlib.RGBToHTML( [hsl[2], hsl[2], hsl[2]] );
this._ui.hs.valMask.css((hsl[2] < 0.5)
? { background : "#000000" , opacity : ( 1.0 - hsl[2] * 2.0 ) }
: { background : "#ffffff" , opacity : ( ( hsl[2] - 0.5 ) * 2.0 ) } );
this._ui.hs.selector.css( {
left : ( hsl[0] / 360 * this._ui.hs.eventSource.width() ),
top : ( hsl[1] * this._ui.hs.eventSource.height() )
});
this._ui.l.selector.css({
top : ( hsl[2] * this._ui.l.eventSource.height() ),
background : gray
} );
$.tizen.colorwidget.prototype._setColor.call( this, clr );
},
widget: function () { return this._ui.clrpicker; },
_setDisabled: function ( value ) {
$.tizen.widgetex.prototype._setDisabled.call( this, value );
this._ui.hs.hueGradient.huegradient( "option", "disabled", value );
this._ui.clrpicker[value ? "addClass" : "removeClass"]( "ui-disabled" );
$.tizen.colorwidget.prototype._displayDisabledState.call( this, this._ui.clrpicker );
},
_setColor: function ( clr ) {
if ( $.tizen.colorwidget.prototype._setColor.call( this, clr ) ) {
this.dragging_hsl = $.tizen.colorwidget.clrlib.RGBToHSL( $.tizen.colorwidget.clrlib.HTMLToRGB( this.options.color ) );
this.dragging_hsl[1] = 1.0 - this.dragging_hsl[1];
this._updateSelectors( this.dragging_hsl );
}
}
} );
$( document ).bind( "pagecreate create", function ( e ) {
$( $.tizen.colorpicker.prototype.options.initSelector, e.target )
.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
.colorpicker();
} );
}( jQuery ) );
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence ( as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php )
*
* ***************************************************************************
* Copyright ( c ) 2000 - 2011 Samsung Electronics Co., Ltd.
* Copyright ( c ) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files ( the "Software" ),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Gabriel Schulhof <gabriel.schulhof@intel.com>
*/
// Displays a button which, when pressed, opens a popupwindow
// containing hsvpicker.
//
// To apply, add the attribute data-role="colorpickerbutton" to a <div>
// element inside a page. Alternatively, call colorpickerbutton() on an
// element.
//
// Options:
//
// color: String; color displayed on the button and the base color
// of the hsvpicker ( see hsvpicker ).
// initial color can be specified in html using the
// data-color="#ff00ff" attribute or when constructed in
// javascript, eg :
// $( "#mycolorpickerbutton" ).colorpickerbutton( { color: "#ff00ff" } );
// where the html might be :
// <div id="colorpickerbutton"></div>
// The color can be changed post-construction like this :
// $( "#mycolorpickerbutton" ).colorpickerbutton( "option", "color", "#ABCDEF" );
// Default: "#1a8039"
//
// buttonMarkup: String; markup to use for the close button on the popupwindow, eg :
// $( "#mycolorpickerbutton" ).colorpickerbutton( "option","buttonMarkup",
// "<a href='#' data-role='button'>ignored</a>" );
//
// closeText: String; the text to display on the close button on the popupwindow.
// The text set in the buttonMarkup will be ignored and this used instead.
//
// Events:
//
// colorchanged: emitted when the color has been changed and the popupwindow is closed.
( function ( $, undefined ) {
$.widget( "tizen.colorpickerbutton", $.tizen.colorwidget, {
options: {
buttonMarkup: {
theme: null,
inline: true,
corners: true,
shadow: true
},
hideInput: true,
closeText: "Close",
initSelector: "input[type='color'], :jqmData(type='color'), :jqmData(role='colorpickerbutton')"
},
_htmlProto: {
source:
$("<div><div id='colorpickerbutton'>" +
" <a id='colorpickerbutton-button' href='#' data-role='button' aria-haspopup='true'>" +
" <span id='colorpickerbutton-button-contents'>&#x2587;&#x2587;&#x2587;</span>" +
" </a>" +
" <div id='colorpickerbutton-popup-container' class='colorpickerbutton-popup-container-style'>" +
" <div id='colorpickerbutton-popup-hsvpicker' data-role='hsvpicker'></div>" +
" <a id='colorpickerbutton-popup-close-button' href='#' data-role='button'>" +
" <span id='colorpickerbutton-popup-close-button-text'></span>" +
" </a>" +
" </div>" +
"</div>" +
"</div>")
, ui: {
button: "#colorpickerbutton-button",
buttonContents: "#colorpickerbutton-button-contents",
popup: "#colorpickerbutton-popup-container",
hsvpicker: "#colorpickerbutton-popup-hsvpicker",
closeButton: "#colorpickerbutton-popup-close-button",
closeButtonText: "#colorpickerbutton-popup-close-button-text"
}
},
_create: function () {
var self = this;
this.element
.css( "display", "none" )
.after( this._ui.button );
/* Tear apart the proto */
this._ui.popup.insertBefore( this.element ).popupwindow();
this._ui.hsvpicker.hsvpicker();
$.tizen.popupwindow.bindPopupToButton( this._ui.button, this._ui.popup );
this._ui.closeButton.bind( "vclick", function ( event ) {
self._setColor( self._ui.hsvpicker.hsvpicker( "option", "color" ) );
self.close();
} );
this.element.bind( "change keyup blur", function () {
self._setColor( self.element.val() );
} );
},
_setHideInput: function ( value ) {
this.element[value ? "addClass" : "removeClass"]( "ui-colorpickerbutton-input-hidden" );
this.element[value ? "removeClass" : "addClass"]( "ui-colorpickerbutton-input" );
this.element.attr( "data-" + ( $.mobile.ns || "" ) + "hide-input", value );
},
_setColor: function ( clr ) {
if ( $.tizen.colorwidget.prototype._setColor.call( this, clr ) ) {
var clrlib = $.tizen.colorwidget.clrlib;
this._ui.hsvpicker.hsvpicker( "option", "color", this.options.color );
$.tizen.colorwidget.prototype._setElementColor.call( this, this._ui.buttonContents,
clrlib.RGBToHSL( clrlib.HTMLToRGB( this.options.color ) ), "color" );
}
},
_setButtonMarkup: function ( value ) {
this._ui.button.buttonMarkup( value );
this.options.buttonMarkup = value;
value.inline = false;
this._ui.closeButton.buttonMarkup( value );
},
_setCloseText: function ( value ) {
this._ui.closeButtonText.text( value );
this.options.closeText = value;
this.element.attr( "data-" + ( $.mobile.ns || "" ) + "close-text", value );
},
_setDisabled: function ( value ) {
$.tizen.widgetex.prototype._setDisabled.call( this, value );
this._ui.popup.popupwindow( "option", "disabled", value );
this._ui.button[value ? "addClass" : "removeClass"]( "ui-disabled" );
$.tizen.colorwidget.prototype._displayDisabledState.call( this, this._ui.button );
},
open: function () {
this._ui.popup.popupwindow( "open",
this._ui.button.offset().left + this._ui.button.outerWidth() / 2,
this._ui.button.offset().top + this._ui.button.outerHeight() / 2 );
},
_focusButton : function () {
var self = this;
setTimeout( function () {
self._ui.button.focus();
}, 40 );
},
close: function () {
this._focusButton();
this._ui.popup.popupwindow( "close" );
}
} );
//auto self-init widgets
$( document ).bind( "pagecreate create", function ( e ) {
$( $.tizen.colorpickerbutton.prototype.options.initSelector, e.target )
.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
.colorpickerbutton();
} );
}( jQuery ) );
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Gabriel Schulhof <gabriel.schulhof@intel.com>
*/
// Displays the color in text of the form '#RRGGBB' where
// RR, GG, and BB are in hexadecimal.
//
// Apply a colortitle by adding the attribute data-role="colortitle"
// to a <div> element inside a page. Alternatively, call colortitle()
// on an element (see below).
//
// Options:
//
// color: String; the initial color can be specified in html using
// the data-color="#ff00ff" attribute or when constructed
// in javascipt eg
// $("#mycolortitle").colortitle({ color: "#ff00ff" });
// where the html might be :
// <div id="mycolortitle"></div>
// The color can be changed post-construction :
// $("#mycolortitle").colortitle("option", "color", "#ABCDEF");
// Default: "#1a8039".
(function ( $, undefined ) {
$.widget( "tizen.colortitle", $.tizen.colorwidget, {
options: {
initSelector: ":jqmData(role='colortitle')"
},
_htmlProto: {
source:
$("<div><div id='colortitle' class='ui-colortitle jquery-mobile-ui-widget'>" +
" <h1 id='colortitle-string'></h1>" +
"</div>" +
"</div>")
, ui: {
clrtitle: "#colortitle",
header: "#colortitle-string"
}
},
_create: function () {
this.element
.css( "display", "none" )
.after( this._ui.clrtitle );
},
widget: function () { return this._ui.clrtitle; },
_setDisabled: function ( value ) {
$.tizen.widgetex.prototype._setDisabled.call( this, value );
this._ui.clrtitle[value ? "addClass" : "removeClass"]( "ui-disabled" );
},
_setColor: function ( clr ) {
if ( $.tizen.colorwidget.prototype._setColor.call( this, clr ) ) {
this._ui.header.text( this.options.color );
$( this._ui.header ).parent().css( "color", this.options.color );
}
}
} );
$( document ).bind( "pagecreate create", function ( e ) {
$( $.tizen.colortitle.prototype.options.initSelector, e.target )
.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
.colortitle();
} );
}( jQuery ) );
/*
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*/
// Ensure that the given namespace is defined. If not, define it to be an empty object.
// This is kinda like the mkdir -p command.
function ensureNS(ns) {
var nsAr = ns.split("."),
nsSoFar = "";
for (var Nix in nsAr) {
nsSoFar = nsSoFar + (Nix > 0 ? "." : "") + nsAr[Nix];
eval (nsSoFar + " = " + nsSoFar + " || {};");
}
}
/*
* jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
*
* Uses the built in easing capabilities added In jQuery 1.1
* to offer multiple easing options
*
* TERMS OF USE - jQuery Easing
*
* Open source under the BSD License.
*
* Copyright © 2008 George McGinley Smith
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the author nor the names of contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];
jQuery.extend( jQuery.easing,
{
def: 'easeOutQuad',
swing: function (x, t, b, c, d) {
//alert(jQuery.easing.default);
return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
},
easeInQuad: function (x, t, b, c, d) {
return c*(t/=d)*t + b;
},
easeOutQuad: function (x, t, b, c, d) {
return -c *(t/=d)*(t-2) + b;
},
easeInOutQuad: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t + b;
return -c/2 * ((--t)*(t-2) - 1) + b;
},
easeInCubic: function (x, t, b, c, d) {
return c*(t/=d)*t*t + b;
},
easeOutCubic: function (x, t, b, c, d) {
return c*((t=t/d-1)*t*t + 1) + b;
},
easeInOutCubic: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t + b;
return c/2*((t-=2)*t*t + 2) + b;
},
easeInQuart: function (x, t, b, c, d) {
return c*(t/=d)*t*t*t + b;
},
easeOutQuart: function (x, t, b, c, d) {
return -c * ((t=t/d-1)*t*t*t - 1) + b;
},
easeInOutQuart: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
return -c/2 * ((t-=2)*t*t*t - 2) + b;
},
easeInQuint: function (x, t, b, c, d) {
return c*(t/=d)*t*t*t*t + b;
},
easeOutQuint: function (x, t, b, c, d) {
return c*((t=t/d-1)*t*t*t*t + 1) + b;
},
easeInOutQuint: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
return c/2*((t-=2)*t*t*t*t + 2) + b;
},
easeInSine: function (x, t, b, c, d) {
return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
},
easeOutSine: function (x, t, b, c, d) {
return c * Math.sin(t/d * (Math.PI/2)) + b;
},
easeInOutSine: function (x, t, b, c, d) {
return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
},
easeInExpo: function (x, t, b, c, d) {
return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
},
easeOutExpo: function (x, t, b, c, d) {
return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
},
easeInOutExpo: function (x, t, b, c, d) {
if (t==0) return b;
if (t==d) return b+c;
if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
},
easeInCirc: function (x, t, b, c, d) {
return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
},
easeOutCirc: function (x, t, b, c, d) {
return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
},
easeInOutCirc: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
},
easeInElastic: function (x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
},
easeOutElastic: function (x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
},
easeInOutElastic: function (x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
},
easeInBack: function (x, t, b, c, d, s) {
if (s == undefined) s = 1.70158;
return c*(t/=d)*t*((s+1)*t - s) + b;
},
easeOutBack: function (x, t, b, c, d, s) {
if (s == undefined) s = 1.70158;
return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
},
easeInOutBack: function (x, t, b, c, d, s) {
if (s == undefined) s = 1.70158;
if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
},
easeInBounce: function (x, t, b, c, d) {
return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
},
easeOutBounce: function (x, t, b, c, d) {
if ((t/=d) < (1/2.75)) {
return c*(7.5625*t*t) + b;
} else if (t < (2/2.75)) {
return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
} else if (t < (2.5/2.75)) {
return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
} else {
return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
}
},
easeInOutBounce: function (x, t, b, c, d) {
if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
}
});
/*
*
* TERMS OF USE - EASING EQUATIONS
*
* Open source under the BSD License.
*
* Copyright © 2001 Robert Penner
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the author nor the names of contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*/
// Add markup for labels
(function($, undefined) {
$(document).bind("pagecreate create", function(e) {
$(":jqmData(role='label')", e.target).not(":jqmData(role='none'), :jqmData(role='nojs')").each(function() {
$(this).addClass("jquery-mobile-ui-label")
.html($("<span>", {"class": "jquery-mobile-ui-label-text"}).text($(this).text()));
});
});
})(jQuery);
/*
* Size pages to the window
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*/
// Size pages to the window
(function($, undefined) {
var _fit_page_to_window_selector = ":jqmData(role='page'):jqmData(fit-page-to-window='true'):visible";
$(document).bind("pageshow", function(e) {
if ($(e.target).is(_fit_page_to_window_selector))
$.mobile.tizen.fillPageWithContentArea($(e.target));
});
$(window).resize(function() {
if ($(_fit_page_to_window_selector)[0] !== undefined)
$.mobile.tizen.fillPageWithContentArea($(_fit_page_to_window_selector));
});
})(jQuery);
ensureNS("jQuery.mobile.tizen.clrlib");
jQuery.extend( jQuery.mobile.tizen.clrlib,
{
nearestInt: function(val) {
var theFloor = Math.floor(val);
return (((val - theFloor) > 0.5) ? (theFloor + 1) : theFloor);
},
/*
* Converts html color string to rgb array.
*
* Input: string clr_str, where
* clr_str is of the form "#aabbcc"
*
* Returns: [ r, g, b ], where
* r is in [0, 1]
* g is in [0, 1]
* b is in [0, 1]
*/
HTMLToRGB: function(clr_str) {
clr_str = (('#' == clr_str.charAt(0)) ? clr_str.substring(1) : clr_str);
return ([
clr_str.substring(0, 2),
clr_str.substring(2, 4),
clr_str.substring(4, 6)
].map(function(val) {
return parseInt(val, 16) / 255.0;
}));
},
/*
* Converts rgb array to html color string.
*
* Input: [ r, g, b ], where
* r is in [0, 1]
* g is in [0, 1]
* b is in [0, 1]
*
* Returns: string of the form "#aabbcc"
*/
RGBToHTML: function(rgb) {
return ("#" +
rgb.map(function(val) {
var ret = val * 255,
theFloor = Math.floor(ret);
ret = ((ret - theFloor > 0.5) ? (theFloor + 1) : theFloor);
ret = (((ret < 16) ? "0" : "") + (ret & 0xff).toString(16));
return ret;
})
.join(""));
},
/*
* Converts hsl to rgb.
*
* From http://130.113.54.154/~monger/hsl-rgb.html
*
* Input: [ h, s, l ], where
* h is in [0, 360]
* s is in [0, 1]
* l is in [0, 1]
*
* Returns: [ r, g, b ], where
* r is in [0, 1]
* g is in [0, 1]
* b is in [0, 1]
*/
HSLToRGB: function(hsl) {
var h = hsl[0] / 360.0, s = hsl[1], l = hsl[2];
if (0 === s)
return [ l, l, l ];
var temp2 = ((l < 0.5)
? l * (1.0 + s)
: l + s - l * s),
temp1 = 2.0 * l - temp2,
temp3 = {
r: h + 1.0 / 3.0,
g: h,
b: h - 1.0 / 3.0
};
temp3.r = ((temp3.r < 0) ? (temp3.r + 1.0) : ((temp3.r > 1) ? (temp3.r - 1.0) : temp3.r));
temp3.g = ((temp3.g < 0) ? (temp3.g + 1.0) : ((temp3.g > 1) ? (temp3.g - 1.0) : temp3.g));
temp3.b = ((temp3.b < 0) ? (temp3.b + 1.0) : ((temp3.b > 1) ? (temp3.b - 1.0) : temp3.b));
ret = [
(((6.0 * temp3.r) < 1) ? (temp1 + (temp2 - temp1) * 6.0 * temp3.r) :
(((2.0 * temp3.r) < 1) ? temp2 :
(((3.0 * temp3.r) < 2) ? (temp1 + (temp2 - temp1) * ((2.0 / 3.0) - temp3.r) * 6.0) :
temp1))),
(((6.0 * temp3.g) < 1) ? (temp1 + (temp2 - temp1) * 6.0 * temp3.g) :
(((2.0 * temp3.g) < 1) ? temp2 :
(((3.0 * temp3.g) < 2) ? (temp1 + (temp2 - temp1) * ((2.0 / 3.0) - temp3.g) * 6.0) :
temp1))),
(((6.0 * temp3.b) < 1) ? (temp1 + (temp2 - temp1) * 6.0 * temp3.b) :
(((2.0 * temp3.b) < 1) ? temp2 :
(((3.0 * temp3.b) < 2) ? (temp1 + (temp2 - temp1) * ((2.0 / 3.0) - temp3.b) * 6.0) :
temp1)))];
return ret;
},
/*
* Converts hsv to rgb.
*
* Input: [ h, s, v ], where
* h is in [0, 360]
* s is in [0, 1]
* v is in [0, 1]
*
* Returns: [ r, g, b ], where
* r is in [0, 1]
* g is in [0, 1]
* b is in [0, 1]
*/
HSVToRGB: function(hsv) {
return $.mobile.tizen.clrlib.HSLToRGB($.mobile.tizen.clrlib.HSVToHSL(hsv));
},
/*
* Converts rgb to hsv.
*
* from http://coecsl.ece.illinois.edu/ge423/spring05/group8/FinalProject/HSV_writeup.pdf
*
* Input: [ r, g, b ], where
* r is in [0, 1]
* g is in [0, 1]
* b is in [0, 1]
*
* Returns: [ h, s, v ], where
* h is in [0, 360]
* s is in [0, 1]
* v is in [0, 1]
*/
RGBToHSV: function(rgb) {
var min, max, delta, h, s, v, r = rgb[0], g = rgb[1], b = rgb[2];
min = Math.min(r, Math.min(g, b));
max = Math.max(r, Math.max(g, b));
delta = max - min;
h = 0;
s = 0;
v = max;
if (delta > 0.00001) {
s = delta / max;
if (r === max)
h = (g - b) / delta ;
else
if (g === max)
h = 2 + (b - r) / delta ;
else
h = 4 + (r - g) / delta ;
h *= 60 ;
if (h < 0)
h += 360 ;
}
return [h, s, v];
},
/*
* Converts hsv to hsl.
*
* Input: [ h, s, v ], where
* h is in [0, 360]
* s is in [0, 1]
* v is in [0, 1]
*
* Returns: [ h, s, l ], where
* h is in [0, 360]
* s is in [0, 1]
* l is in [0, 1]
*/
HSVToHSL: function(hsv) {
var max = hsv[2],
delta = hsv[1] * max,
min = max - delta,
sum = max + min,
half_sum = sum / 2,
s_divisor = ((half_sum < 0.5) ? sum : (2 - max - min));
return [ hsv[0], ((0 == s_divisor) ? 0 : (delta / s_divisor)), half_sum ];
},
/*
* Converts rgb to hsl
*
* Input: [ r, g, b ], where
* r is in [0, 1]
* g is in [0, 1]
* b is in [0, 1]
*
* Returns: [ h, s, l ], where
* h is in [0, 360]
* s is in [0, 1]
* l is in [0, 1]
*/
RGBToHSL: function(rgb) {
return $.mobile.tizen.clrlib.HSVToHSL($.mobile.tizen.clrlib.RGBToHSV(rgb));
}
});
/*!
* jQuery Mobile Widget @VERSION
*
* TODO: remove unnecessary codes....
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Kalyan Kondapally <kalyan.kondapally@intel.com>
*/
ensureNS("jQuery.mobile.tizen");
(function () {
jQuery.extend(jQuery.mobile.tizen, {
Point: function (x, y) {
var X = isNaN(x) ? 0 : x;
var Y = isNaN(y) ? 0 : y;
this.add = function (Point) {
this.setX(X + Point.x());
this.setY(Y + Point.y());
return this;
}
this.subtract = function (Point) {
this.setX(X - Point.x());
this.setY(Y - Point.y());
return this;
}
this.multiply = function (Point) {
this.setX(Math.round(X * Point.x()));
this.setY(Math.round(Y * Point.y()));
return this;
}
this.divide = function (Point) {
this.setX(Math.round(X / Point.x()));
this.setY(Math.round(Y / Point.y()));
return this;
}
this.isNull = function () {
return (X === 0 && Y === 0);
}
this.x = function () {
return X;
}
this.setX = function (val) {
isNaN(val) ? X = 0 : X = val;
}
this.y = function () {
return Y;
}
this.setY = function (val) {
isNaN(val) ? Y = 0 : Y = val;
}
this.setNewPoint = function (point) {
this.setX(point.x());
this.setY(point.y());
}
this.isEqualTo = function (point) {
return (X === point.x() && Y === point.y());
}
},
Rect: function (left,top,width,height) {
var Left = left;
var Top = top;
var Right = Left+width;
var Bottom = Top+height;
this.setRect = function(varL,varR,varT,varB) {
this.setLeft(varL);
this.setRight(varR);
this.setTop(varT);
this.setBottom(varB);
}
this.right = function () {
return Right;
}
this.setRight = function (val) {
Right = val;
}
this.top = function () {
return Top;
}
this.setTop = function (val) {
Top = val;
}
this.bottom = function () {
return Bottom;
}
this.setBottom = function (val) {
Bottom = val;
}
this.left = function () {
return Left;
}
this.setLeft = function (val) {
Left = val;
}
this.moveTop = function(valY) {
var h = this.height();
Top = valY;
Bottom = Top + h;
}
this.isNull = function () {
return Right === Left && Bottom === Top;
}
this.isValid = function () {
return Left <= Right && Top <= Bottom;
}
this.isEmpty = function () {
return Left > Right || Top > Bottom;
}
this.contains = function (valX,valY) {
if (this.containsX(valX) && this.containsY(valY))
return true;
return false;
}
this.width = function () {
return Right - Left;
}
this.height = function () {
return Bottom - Top;
}
this.containsX = function(val) {
var l = Left,
r = Right;
if (Right<Left) {
l = Right;
r = Left;
}
if (l > val || r < val)
return false;
return true;
}
this.containsY = function(val) {
var t = Top,
b = Bottom;
if (Bottom<Top) {
t = Bottom;
b = Top;
}
if (t > val || b < val)
return false;
return true;
}
},
disableSelection: function (element) {
return $(element).each(function () {
jQuery(element).css('-webkit-user-select', 'none');
});
},
enableSelection: function (element, value) {
return $(element).each(function () {
val = value == "text" ? val = 'text' : val = 'auto';
jQuery(element).css('-webkit-user-select', val);
});
},
// Set the height of the content area to fill the space between a
// page's header and footer
fillPageWithContentArea: function (page) {
var $page = $(page);
var $content = $page.children(".ui-content:first");
var hh = $page.children(".ui-header").outerHeight(); hh = hh ? hh : 0;
var fh = $page.children(".ui-footer").outerHeight(); fh = fh ? fh : 0;
var pt = parseFloat($content.css("padding-top"));
var pb = parseFloat($content.css("padding-bottom"));
var wh = window.innerHeight;
var height = wh - (hh + fh) - (pt + pb);
$content.height(height);
},
// Get document-relative mouse coordinates from a given event
// From: http://www.quirksmode.org/js/events_properties.html#position
documentRelativeCoordsFromEvent: function(ev) {
var e = ev ? ev : window.event,
client = { x: e.clientX, y: e.clientY },
page = { x: e.pageX, y: e.pageY },
posx = 0,
posy = 0;
// Grab useful coordinates from touch events
if (e.type.match(/^touch/)) {
page = {
x: e.originalEvent.targetTouches[0].pageX,
y: e.originalEvent.targetTouches[0].pageY
};
client = {
x: e.originalEvent.targetTouches[0].clientX,
y: e.originalEvent.targetTouches[0].clientY
};
}
if (page.x || page.y) {
posx = page.x;
posy = page.y;
}
else
if (client.x || client.y) {
posx = client.x + document.body.scrollLeft + document.documentElement.scrollLeft;
posy = client.y + document.body.scrollTop + document.documentElement.scrollTop;
}
return { x: posx, y: posy };
},
// TODO : offsetX, offsetY. touch events don't have offsetX and offsetY. support for touch devices.
// check algorithm...
targetRelativeCoordsFromEvent: function(e) {
var coords = { x: e.offsetX, y: e.offsetY };
if (coords.x === undefined || isNaN(coords.x) ||
coords.y === undefined || isNaN(coords.y)) {
var offset = $(e.target).offset();
//coords = documentRelativeCoordsFromEvent(e); // Old code. Must be checked again.
coords = $.mobile.tizen.documentRelativeCoordsFromEvent(e);
coords.x -= offset.left;
coords.y -= offset.top;
}
return coords;
}
});
})();
/*
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*/
// Wrapper round the jLayout functions to enable it to be used
// for creating jQuery Mobile layout extensions.
//
// See the layouthbox and layoutvbox widgets for usage examples.
(function ($, undefined) {
$.widget("tizen.jlayoutadaptor", $.mobile.widget, {
options: {
hgap: null,
vgap: null,
scrollable: true,
showScrollBars: true,
direction: null
},
_create: function () {
var self = this,
options = this.element.data('layout-options'),
page = $(this.element).closest(':jqmData(role="page")');
$.extend(this.options, options);
if (page && !page.is(':visible')) {
this.element.hide();
page.bind('pageshow', function () {
self.refresh();
});
}
else {
this.refresh();
}
},
refresh: function () {
var container;
var config = $.extend(this.options, this.fixed);
if (config.scrollable) {
if (!(this.element.children().is('.ui-scrollview-view'))) {
// create the scrollview
this.element.scrollview({direction: config.direction,
showScrollBars: config.showScrollBars});
}
else if (config.showScrollBars) {
this.element.find('.ui-scrollbar').show();
}
else {
this.element.find('.ui-scrollbar').hide();
}
container = this.element.find('.ui-scrollview-view');
}
else {
container = this.element;
}
container.layout(config);
this.element.show();
if (config.scrollable) {
// get the right/bottom edge of the last child after layout
var lastItem = container.children().last();
var edge;
var scrollview = this.element.find('.ui-scrollview-view');
if (config.direction === 'x') {
edge = lastItem.position().left +
lastItem.outerWidth(true);
// set the scrollview's view width to the original width
scrollview.width(edge);
// set the parent container's height to the height of
// the scrollview
this.element.height(scrollview.height());
}
else if (config.direction === 'y') {
edge = lastItem.position().top +
lastItem.outerHeight(true);
// set the scrollview's view height to the original height
scrollview.height(edge);
// set the parent container's width to the width of the
// scrollview
this.element.width(scrollview.width());
}
}
}
});
})(jQuery);
(function($, undefined) {
ensureNS("jQuery.mobile.tizen");
jQuery.extend( jQuery.mobile.tizen,
{
_widgetPrototypes: {},
/*
* load the prototype for a widget.
*
* If @widget is a string, the function looks for @widget.prototype.html in the proto-html/ subdirectory of the
* framework's current theme and loads the file via AJAX into a string. Note that the file will only be loaded via
* AJAX once. If two widget instances based on the same @widget value are to be constructed, the second will be
* constructed from the cached copy of the prototype of the first instance.
*
* If @widget is not a string, it is assumed to be a hash containing at least one key, "proto", the value of which is
* the string to be used for the widget prototype. if another key named "key" is also provided, it will serve as the
* key under which to cache the prototype, so it need not be rendered again in the future.
*
* Given the string for the widget prototype, the following patterns occurring in the string are replaced:
*
* "${FRAMEWORK_ROOT}" - replaced with the path to the root of the framework
*
* The function then creates a jQuery $("<div>") object containing the prototype from the string.
*
* If @ui is not provided, the jQuery object containing the prototype is returned.
*
* If @ui is provided, it is assumed to be a (possibly multi-level) hash containing CSS selectors. For every level of
* the hash and for each string-valued key at that level, the CSS selector specified as the value is sought in the
* prototype jQuery object and, if found, the value of the key is replaced with the jQuery object resulting from the
* search. Additionally, if the CSS selector is of the form "#widgetid", the "id" attribute will be removed from the
* elements contained within the resulting jQuery object. The resulting hash is returned.
*
* Examples:
*
* 1.
* $.mobile.tizen.loadPrototype("mywidget") => Returns a <div> containing the structure from the file
* mywidget.prototype.html located in the current theme folder of the current framework.
*
* 2. $.mobile.tizen.loadPrototype("mywidget", ui):
* where ui is a hash that looks like this:
* ui = {
* element1: "<css selector 1>",
* element2: "<css selector 2>",
* group1: {
* group1element1: "<css selector 3>",
* group1element1: "<css selector 4>"
* }
* ...
* }
*
* In this case, after loading the prototype as in Example 1, loadPrototype will traverse @ui and replace the CSS
* selector strings with the result of the search for the selector string upon the prototype. If any of the CSS
* selectors are of the form "#elementid" then the "id" attribute will be stripped from the elements selected. This
* means that they will no longer be accessible via the selector used initially. @ui is then returned thus modified.
*/
loadPrototype: function(widget, ui) {
var ret = undefined,
theScriptTag = $("script[data-framework-version][data-framework-root][data-framework-theme]"),
frameworkRootPath = theScriptTag.attr("data-framework-root") + "/" +
theScriptTag.attr("data-framework-version") + "/";
function replaceVariables(s) {
return s.replace(/\$\{FRAMEWORK_ROOT\}/g, frameworkRootPath);
}
function fillObj(obj, uiProto) {
var selector;
for (var key in obj) {
if (typeof obj[key] === "string") {
selector = obj[key];
obj[key] = uiProto.find(obj[key]);
if (selector.substring(0, 1) === "#")
obj[key].removeAttr("id");
}
else
if (typeof obj[key] === "object")
obj[key] = fillObj(obj[key], uiProto);
}
return obj;
}
/* If @widget is a string ... */
if (typeof widget === "string") {
/* ... try to use it as a key into the cached prototype hash ... */
ret = $.mobile.tizen._widgetPrototypes[widget];
if (ret === undefined) {
/* ... and if the proto was not found, try to load its definition ... */
var protoPath = frameworkRootPath + "proto-html" + "/" +
theScriptTag.attr("data-framework-theme");
$.ajax({
url: protoPath + "/" + widget + ".prototype.html",
async: false,
dataType: "html"
})
.success(function(data, textStatus, jqXHR) {
/* ... and if loading succeeds, cache it and use a copy of it ... */
$.mobile.tizen._widgetPrototypes[widget] = $("<div>").html(replaceVariables(data));
ret = $.mobile.tizen._widgetPrototypes[widget].clone();
});
}
}
/* Otherwise ... */
else {
/* ... if a key was provided ... */
if (widget.key !== undefined)
/* ... try to use it as a key into the cached prototype hash ... */
ret = $.mobile.tizen._widgetPrototypes[widget.key];
/* ... and if the proto was not found in the cache ... */
if (ret === undefined) {
/* ... and a proto definition string was provided ... */
if (widget.proto !== undefined) {
/* ... create a new proto from the definition ... */
ret = $("<div>").html(replaceVariables(widget.proto));
/* ... and if a key was provided ... */
if (widget.key !== undefined)
/* ... cache a copy of the proto under that key */
$.mobile.tizen._widgetPrototypes[widget.key] = ret.clone();
}
}
else
/* otherwise, if the proto /was/ found in the cache, return a copy of it */
ret = ret.clone();
}
/* If the prototype was found/created successfully ... */
if (ret != undefined)
/* ... and @ui was provided */
if (ui != undefined)
/* ... return @ui, but replace the CSS selectors it contains with the elements they select */
ret = fillObj(ui, ret);
return ret;
}
});
})(jQuery);
/*
* jQuery Mobile Framework : scrollview plugin
* Copyright (c) 2010 Adobe Systems Incorporated - Kin Blas (jblas@adobe.com)
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
* Note: Code is in draft form and is subject to change
* Modified by Koeun Choi <koeun.choi@samsung.com>
* Modified by Minkyu Kang <mk7.kang@samsung.com>
*/
(function ( $, window, document, undefined ) {
function setElementTransform( $ele, x, y, duration ) {
var v = "translate(" + x + "," + y + ")",
transition;
if ( !duration || duration === undefined ) {
transition = "none";
} else {
transition = "-webkit-transform " + duration / 1000 + "s";
}
$ele.css({
"-moz-transform": v,
"-webkit-transform": v,
"-ms-transform": v,
"-o-transform": v,
"transform": v,
"-webkit-transition": transition
});
}
function MomentumTracker( options ) {
this.options = $.extend( {}, options );
this.easing = "easeOutQuad";
this.reset();
}
var tstates = {
scrolling: 0,
overshot: 1,
snapback: 2,
done: 3
};
function getCurrentTime() {
return ( new Date() ).getTime();
}
jQuery.widget( "tizen.scrollview", jQuery.mobile.widget, {
options: {
fps: 60, // Frames per second in msecs.
direction: null, // "x", "y", or null for both.
scrollDuration: 2000, // Duration of the scrolling animation in msecs.
overshootDuration: 250, // Duration of the overshoot animation in msecs.
snapbackDuration: 500, // Duration of the snapback animation in msecs.
moveThreshold: 50, // User must move this many pixels in any direction to trigger a scroll.
moveIntervalThreshold: 150, // Time between mousemoves must not exceed this threshold.
scrollMethod: "translate", // "translate", "position", "scroll"
startEventName: "scrollstart",
updateEventName: "scrollupdate",
stopEventName: "scrollstop",
eventType: $.support.touch ? "touch" : "mouse",
showScrollBars: true,
pagingEnabled: false,
overshootEnable: false,
delayedClickSelector: "a,input,textarea,select,button,.ui-btn"
},
_makePositioned: function ( $ele ) {
if ( $ele.css("position") === "static" ) {
$ele.css( "position", "relative" );
}
},
_create: function () {
var $page = $('.ui-page'),
$child,
direction,
self = this;
this._$clip = $( this.element ).addClass("ui-scrollview-clip");
$child = this._$clip.wrapInner("<div></div>").children();
this._$view = $child.addClass("ui-scrollview-view");
if ( this.options.scrollMethod === "translate" ) {
if ( this._$view.css("transform") === undefined ) {
this.options.scrollMethod = "position";
}
}
this._$clip.css( "overflow",
this.options.scrollMethod === "scroll" ? "scroll" : "hidden" );
this._makePositioned( this._$clip );
/*
* Turn off our faux scrollbars if we are using native scrolling
* to position the view.
*/
if ( this.options.scrollMethod === "scroll" ) {
this.options.showScrollBars = false;
}
/*
* We really don't need this if we are using a translate transformation
* for scrolling. We set it just in case the user wants to switch methods
* on the fly.
*/
this._makePositioned( this._$view );
this._$view.css({ left: 0, top: 0 });
this._sx = 0;
this._sy = 0;
direction = this.options.direction;
this._hTracker = ( direction !== "y" ) ?
new MomentumTracker( this.options ) : null;
this._vTracker = ( direction !== "x" ) ?
new MomentumTracker( this.options ) : null;
this._timerInterval = 1000 / this.options.fps;
this._timerID = 0;
this._timerCB = function () {
self._handleMomentumScroll();
};
this._addBehaviors();
},
_startMScroll: function ( speedX, speedY ) {
this._stopMScroll();
this._showScrollBars();
var keepGoing = false,
duration = this.options.scrollDuration,
ht = this._hTracker,
vt = this._vTracker,
c,
v;
this._$clip.trigger( this.options.startEventName );
$( document ).trigger("scrollview_scroll");
if ( ht ) {
c = this._$clip.width();
v = this._$view.width();
ht.start( this._sx, speedX,
duration, (v > c) ? -(v - c) : 0, 0 );
keepGoing = !ht.done();
}
if ( vt ) {
c = this._$clip.height();
v = this._$view.height() +
parseFloat( this._$view.css("padding-top") );
vt.start( this._sy, speedY,
duration, (v > c) ? -(v - c) : 0, 0 );
keepGoing = keepGoing || !vt.done();
}
if ( keepGoing ) {
this._timerID = setTimeout( this._timerCB, this._timerInterval );
} else {
this._stopMScroll();
}
},
_stopMScroll: function () {
if ( this._timerID ) {
this._$clip.trigger( this.options.stopEventName );
clearTimeout( this._timerID );
}
this._timerID = 0;
if ( this._vTracker ) {
this._vTracker.reset();
}
if ( this._hTracker ) {
this._hTracker.reset();
}
this._hideScrollBars();
},
_handleMomentumScroll: function () {
var keepGoing = false,
v = this._$view,
x = 0,
y = 0,
vt = this._vTracker,
ht = this._hTracker;
if ( vt ) {
vt.update( this.options.overshootEnable );
y = vt.getPosition();
keepGoing = !vt.done();
}
if ( ht ) {
ht.update( this.options.overshootEnable );
x = ht.getPosition();
keepGoing = keepGoing || !ht.done();
}
this._setScrollPosition( x, y );
this._$clip.trigger( this.options.updateEventName,
[ { x: x, y: y } ] );
if ( keepGoing ) {
this._timerID = setTimeout( this._timerCB, this._timerInterval );
} else {
this._stopMScroll();
}
},
_setCalibration: function ( x, y ) {
if ( this.options.overshootEnable ) {
this._sx = x;
this._sy = y;
return;
}
var v = this._$view,
c = this._$clip,
dirLock = this._directionLock,
scroll_height = 0;
if ( dirLock !== "y" && this._hTracker ) {
this._sx = x;
}
if ( dirLock !== "x" && this._vTracker ) {
scroll_height = v.height() - c.height() +
parseFloat( c.css("padding-top") ) +
parseFloat( c.css("padding-bottom") );
if ( y >= 0 ) {
this._sy = 0;
} else if ( y < -scroll_height ) {
this._sy = -scroll_height;
} else {
this._sy = y;
}
if ( scroll_height < 0 ) {
this._sy = 0;
}
}
},
_setScrollPosition: function ( x, y, duration ) {
this._setCalibration( x, y );
x = this._sx;
y = this._sy;
var $v = this._$view,
sm = this.options.scrollMethod,
$vsb = this._$vScrollBar,
$hsb = this._$hScrollBar,
$sbt;
switch ( sm ) {
case "translate":
setElementTransform( $v, x + "px", y + "px", duration );
break;
case "position":
$v.css({left: x + "px", top: y + "px"});
break;
case "scroll":
this._$clip[0].scrollLeft = -x;
this._$clip[0].scrollTop = -y;
break;
}
if ( $vsb ) {
$sbt = $vsb.find(".ui-scrollbar-thumb");
if ( sm === "translate" ) {
setElementTransform( $sbt, "0px",
-y / $v.height() * $sbt.parent().height() + "px",
duration );
} else {
$sbt.css( "top", -y / $v.height() * 100 + "%" );
}
}
if ( $hsb ) {
$sbt = $hsb.find(".ui-scrollbar-thumb");
if ( sm === "translate" ) {
setElementTransform( $sbt,
-x / $v.width() * $sbt.parent().width() + "px", "0px",
duration);
} else {
$sbt.css("left", -x / $v.width() * 100 + "%");
}
}
},
scrollTo: function ( x, y, duration ) {
this._stopMScroll();
/*
* currently support only animation for translate
* Don't want to use setTimeout algorithm for animation.
*/
if ( !duration || (duration && this.options.scrollMethod === "translate") ) {
return this._setScrollPosition( x, y, duration );
}
// follow jqm default animation when the scrollmethod is not translate.
x = -x;
y = -y;
var self = this,
start = getCurrentTime(),
efunc = $.easing.easeOutQuad,
sx = this._sx,
sy = this._sy,
dx = x - sx,
dy = y - sy,
tfunc;
tfunc = function () {
var elapsed = getCurrentTime() - start,
ec;
if ( elapsed >= duration ) {
self._timerID = 0;
self._setScrollPosition( x, y );
} else {
ec = efunc( elapsed / duration, elapsed, 0, 1, duration );
self._setScrollPosition( sx + (dx * ec), sy + (dy * ec) );
self._timerID = setTimeout( tfunc, self._timerInterval );
}
};
this._timerID = setTimeout( tfunc, this._timerInterval );
},
getScrollPosition: function () {
return { x: -this._sx, y: -this._sy };
},
_getScrollHierarchy: function () {
var svh = [],
d;
this._$clip.parents(".ui-scrollview-clip").each(function () {
d = $( this ).jqmData("scrollview");
if ( d ) {
svh.unshift( d );
}
});
return svh;
},
_getAncestorByDirection: function ( dir ) {
var svh = this._getScrollHierarchy(),
n = svh.length,
sv,
svdir;
while ( 0 < n-- ) {
sv = svh[n];
svdir = sv.options.direction;
if (!svdir || svdir === dir) {
return sv;
}
}
return null;
},
_handleDragStart: function ( e, ex, ey ) {
// Stop any scrolling of elements in our parent hierarcy.
$.each( this._getScrollHierarchy(), function (i, sv) {
sv._stopMScroll();
});
this._stopMScroll();
this._didDrag = false;
var target = $( e.target ),
shouldBlockEvent = 1,
c = this._$clip,
v = this._$view,
cw = 0,
vw = 0,
ch = 0,
vh = 0,
svdir = this.options.direction,
thumb;
// should skip the dragging when click the button
this._skip_dragging = target.is('.ui-btn-text') ||
target.is('.ui-btn-inner');
if ( this._skip_dragging ) {
return;
}
/*
* If we're using mouse events, we need to prevent the default
* behavior to suppress accidental selection of text, etc. We
* can't do this on touch devices because it will disable the
* generation of "click" events.
*/
this._shouldBlockEvent = !( target.is(':input') ||
target.parents(':input').length > 0 );
if ( this._shouldBlockEvent ) {
e.preventDefault();
}
this._lastX = ex;
this._lastY = ey;
this._startY = ey;
this._doSnapBackX = false;
this._doSnapBackY = false;
this._speedX = 0;
this._speedY = 0;
this._directionLock = "";
if ( this._hTracker ) {
cw = parseInt( c.css("width"), 10 );
vw = parseInt( v.css("width"), 10 );
this._maxX = cw - vw;
if ( this._maxX > 0 ) {
this._maxX = 0;
}
if ( this._$hScrollBar && vw ) {
thumb = this._$hScrollBar.find(".ui-scrollbar-thumb");
thumb.css( "width", (cw >= vw ? "100%" :
(Math.floor(cw / vw * 100) || 1) + "%") );
}
}
if ( this._vTracker ) {
ch = parseInt( c.css("height"), 10 );
vh = parseInt( v.css("height"), 10 ) +
parseFloat( v.css("padding-top") );
this._maxY = ch - vh;
if ( this._maxY > 0 ) {
this._maxY = 0;
}
if ( this._$vScrollBar && vh ) {
thumb = this._$vScrollBar.find(".ui-scrollbar-thumb");
thumb.css( "height", (ch >= vh ? "100%" :
(Math.floor(ch / vh * 100) || 1) + "%") );
}
}
this._pageDelta = 0;
this._pageSize = 0;
this._pagePos = 0;
if ( this.options.pagingEnabled && (svdir === "x" || svdir === "y") ) {
this._pageSize = (svdir === "x") ? cw : ch;
this._pagePos = (svdir === "x") ? this._sx : this._sy;
this._pagePos -= this._pagePos % this._pageSize;
}
this._lastMove = 0;
this._enableTracking();
},
_propagateDragMove: function ( sv, e, ex, ey, dir ) {
this._hideScrollBars();
this._disableTracking();
sv._handleDragStart( e, ex, ey );
sv._directionLock = dir;
sv._didDrag = this._didDrag;
},
_handleDragMove: function ( e, ex, ey ) {
if ( this._skip_dragging ) {
return;
}
if ( !this._dragging ) {
return;
}
if ( this._shouldBlockEvent ) {
e.preventDefault();
}
var mt = this.options.moveThreshold,
v = this._$view,
dx = ex - this._lastX,
dy = ey - this._lastY,
svdir = this.options.direction,
dir = null,
x,
y,
sv,
scope,
newX,
newY,
dirLock,
opos,
cpos,
delta;
if ( Math.abs( this._startY - ey ) < mt && !this._didDrag ) {
return;
}
this._lastMove = getCurrentTime();
if ( !this._directionLock ) {
x = Math.abs( dx );
y = Math.abs( dy );
if ( x < mt && y < mt ) {
return false;
}
if ( x < y && (x / y) < 0.5 ) {
dir = "y";
} else if ( x > y && (y / x) < 0.5 ) {
dir = "x";
}
if ( svdir && dir && svdir !== dir ) {
/*
* This scrollview can't handle the direction the user
* is attempting to scroll. Find an ancestor scrollview
* that can handle the request.
*/
sv = this._getAncestorByDirection( dir );
if ( sv ) {
this._propagateDragMove( sv, e, ex, ey, dir );
return false;
}
}
//this._directionLock = svdir ? svdir : (dir ? dir : "none");
this._directionLock = svdir || (dir || "none");
}
newX = this._sx;
newY = this._sy;
dirLock = this._directionLock;
if ( dirLock !== "y" && this._hTracker ) {
x = this._sx;
this._speedX = dx;
newX = x + dx;
// Simulate resistance.
this._doSnapBackX = false;
scope = (newX > 0 || newX < this._maxX);
if ( scope && dirLock === "x" ) {
sv = this._getAncestorByDirection("x");
if ( sv ) {
this._setScrollPosition( newX > 0 ?
0 : this._maxX, newY );
this._propagateDragMove( sv, e, ex, ey, dir );
return false;
}
newX = x + (dx / 2);
this._doSnapBackX = true;
}
}
if ( dirLock !== "x" && this._vTracker ) {
y = this._sy;
this._speedY = dy;
newY = y + dy;
// Simulate resistance.
this._doSnapBackY = false;
scope = (newY > 0 || newY < this._maxY);
if ( scope && dirLock === "y" ) {
sv = this._getAncestorByDirection("y");
if ( sv ) {
this._setScrollPosition( newX,
newY > 0 ? 0 : this._maxY );
this._propagateDragMove( sv, e, ex, ey, dir );
return false;
}
newY = y + (dy / 2);
this._doSnapBackY = true;
}
}
if ( this.options.overshootEnable === false ) {
this._doSnapBackX = false;
this._doSnapBackY = false;
}
if ( this.options.pagingEnabled && (svdir === "x" || svdir === "y") ) {
if ( this._doSnapBackX || this._doSnapBackY ) {
this._pageDelta = 0;
} else {
opos = this._pagePos;
cpos = svdir === "x" ? newX : newY;
delta = svdir === "x" ? dx : dy;
if ( opos > cpos && delta < 0 ) {
this._pageDelta = this._pageSize;
} else if ( opos < cpos && delta > 0 ) {
this._pageDelta = -this._pageSize;
} else {
this._pageDelta = 0;
}
}
}
this._didDrag = true;
this._lastX = ex;
this._lastY = ey;
this._setScrollPosition( newX, newY );
this._showScrollBars();
},
_handleDragStop: function ( e ) {
if ( this._skip_dragging ) {
return;
}
var l = this._lastMove,
t = getCurrentTime(),
doScroll = (l && (t - l) <= this.options.moveIntervalThreshold),
sx = ( this._hTracker && this._speedX && doScroll ) ?
this._speedX : ( this._doSnapBackX ? 1 : 0 ),
sy = ( this._vTracker && this._speedY && doScroll ) ?
this._speedY : ( this._doSnapBackY ? 1 : 0 ),
svdir = this.options.direction,
x,
y;
if ( this.options.pagingEnabled && (svdir === "x" || svdir === "y") &&
!this._doSnapBackX && !this._doSnapBackY ) {
x = this._sx;
y = this._sy;
if ( svdir === "x" ) {
x = -this._pagePos + this._pageDelta;
} else {
y = -this._pagePos + this._pageDelta;
}
this.scrollTo( x, y, this.options.snapbackDuration );
} else if ( sx || sy ) {
this._startMScroll( sx, sy );
} else {
this._hideScrollBars();
}
this._disableTracking();
if ( !this._didDrag && this.options.eventType === "touch" ) {
$(e.target).closest(this.options.delayedClickSelector).trigger("click");
}
/*
* If a view scrolled, then we need to absorb
* the event so that links etc, underneath our
* cursor/finger don't fire.
*/
return !this._didDrag;
},
_enableTracking: function () {
this._dragging = true;
},
_disableTracking: function () {
this._dragging = false;
},
_showScrollBars: function () {
var vclass = "ui-scrollbar-visible";
if ( this._$vScrollBar ) {
this._$vScrollBar.addClass( vclass );
}
if ( this._$hScrollBar ) {
this._$hScrollBar.addClass( vclass );
}
},
_hideScrollBars: function () {
var vclass = "ui-scrollbar-visible";
if ( this._$vScrollBar ) {
this._$vScrollBar.removeClass( vclass );
}
if ( this._$hScrollBar ) {
this._$hScrollBar.removeClass( vclass );
}
},
_addBehaviors: function () {
var self = this,
$c = this._$clip,
prefix = "<div class=\"ui-scrollbar ui-scrollbar-",
suffix = "\"><div class=\"ui-scrollbar-track\"><div class=\"ui-scrollbar-thumb\"></div></div></div>";
if ( this.options.eventType === "mouse" ) {
this._dragEvt = "mousedown mousemove mouseup click";
this._dragCB = function ( e ) {
switch ( e.type ) {
case "mousedown":
return self._handleDragStart( e,
e.clientX, e.clientY );
case "mousemove":
return self._handleDragMove( e,
e.clientX, e.clientY );
case "mouseup":
return self._handleDragStop( e );
case "click":
return !self._didDrag;
}
};
} else {
this._dragEvt = "touchstart touchmove touchend vclick";
this._dragCB = function ( e ) {
var t;
switch ( e.type ) {
case "touchstart":
t = e.originalEvent.targetTouches[0];
return self._handleDragStart( e,
t.pageX, t.pageY );
case "touchmove":
t = e.originalEvent.targetTouches[0];
return self._handleDragMove( e,
t.pageX, t.pageY );
case "touchend":
return self._handleDragStop( e );
case "vclick":
return !self._didDrag;
}
};
}
this._$view.bind( this._dragEvt, this._dragCB );
if ( this.options.showScrollBars ) {
if ( this._vTracker ) {
$c.append( prefix + "y" + suffix );
this._$vScrollBar = $c.children(".ui-scrollbar-y");
}
if ( this._hTracker ) {
$c.append( prefix + "x" + suffix );
this._$hScrollBar = $c.children(".ui-scrollbar-x");
}
}
}
});
$.extend( MomentumTracker.prototype, {
start: function ( pos, speed, duration, minPos, maxPos ) {
var tstate = (pos < minPos || pos > maxPos) ?
tstates.snapback : tstates.scrolling,
pos_temp;
this.state = (speed !== 0) ? tstate : tstates.done;
this.pos = pos;
this.speed = speed;
this.duration = (this.state === tstates.snapback) ?
this.options.snapbackDuration : duration;
this.minPos = minPos;
this.maxPos = maxPos;
this.fromPos = (this.state === tstates.snapback) ? this.pos : 0;
pos_temp = (this.pos < this.minPos) ? this.minPos : this.maxPos;
this.toPos = (this.state === tstates.snapback) ? pos_temp : 0;
this.startTime = getCurrentTime();
},
reset: function () {
this.state = tstates.done;
this.pos = 0;
this.speed = 0;
this.minPos = 0;
this.maxPos = 0;
this.duration = 0;
},
update: function ( overshootEnable ) {
var state = this.state,
cur_time = getCurrentTime(),
duration = this.duration,
elapsed = cur_time - this.startTime,
dx,
x,
didOverShoot;
if ( state === tstates.done ) {
return this.pos;
}
elapsed = elapsed > duration ? duration : elapsed;
if ( state === tstates.scrolling || state === tstates.overshot ) {
dx = this.speed *
(1 - $.easing[this.easing]( elapsed / duration,
elapsed, 0, 1, duration ));
x = this.pos + dx;
didOverShoot = (state === tstates.scrolling) &&
(x < this.minPos || x > this.maxPos);
if ( didOverShoot ) {
x = (x < this.minPos) ? this.minPos : this.maxPos;
}
this.pos = x;
if ( state === tstates.overshot ) {
if ( elapsed >= duration ) {
this.state = tstates.snapback;
this.fromPos = this.pos;
this.toPos = (x < this.minPos) ?
this.minPos : this.maxPos;
this.duration = this.options.snapbackDuration;
this.startTime = cur_time;
elapsed = 0;
}
} else if ( state === tstates.scrolling ) {
if ( didOverShoot && overshootEnable ) {
this.state = tstates.overshot;
this.speed = dx / 2;
this.duration = this.options.overshootDuration;
this.startTime = cur_time;
} else if ( elapsed >= duration ) {
this.state = tstates.done;
}
}
} else if ( state === tstates.snapback ) {
if ( elapsed >= duration ) {
this.pos = this.toPos;
this.state = tstates.done;
} else {
this.pos = this.fromPos + ((this.toPos - this.fromPos) *
$.easing[this.easing]( elapsed / duration,
elapsed, 0, 1, duration ));
}
}
return this.pos;
},
done: function () {
return this.state === tstates.done;
},
getPosition: function () {
return this.pos;
}
});
function resizePageContentHeight( page ) {
var $page = $( page ),
$content = $page.children(".ui-content"),
hh = $page.children(".ui-header").outerHeight() || 0,
fh = $page.children(".ui-footer").outerHeight() || 0,
pt = parseFloat( $content.css("padding-top") ),
pb = parseFloat( $content.css("padding-bottom") ),
wh = $(window).height();
$content.height( wh - (hh + fh) - (pt + pb) );
}
// auto-init scrollview and scrolllistview widgets
$( document ).bind( 'pagecreate create', function ( e ) {
var $page = $( e.target ),
scroll = $page.find(".ui-content").attr("data-scroll");
if ( scroll === "none" ) {
return;
}
if ( $.support.scrollview === undefined ) {
// set as default value
$.support.scrollview = true;
}
if ( $.support.scrollview === true && scroll === undefined ) {
$page.find(".ui-content").attr( "data-scroll", "y" );
}
$page.find(":jqmData(scroll):not(.ui-scrollview-clip)").each( function () {
if ( $( this ).hasClass("ui-scrolllistview") ) {
$( this ).scrolllistview();
} else {
var st = $( this ).jqmData("scroll"),
paging = st && (st.search(/^[xy]p$/) !== -1),
dir = st && (st.search(/^[xy]/) !== -1) ? st.charAt(0) : null,
opts;
opts = {
direction: dir || undefined,
paging: paging || undefined,
scrollMethod: $( this ).jqmData("scroll-method") || undefined
};
$( this ).scrollview( opts );
}
});
});
$( document ).bind( 'pageshow', function ( e ) {
var $page = $( e.target ),
scroll = $page.find(".ui-content").attr("data-scroll");
if ( scroll === "y" ) {
setTimeout( function () {
resizePageContentHeight( e.target );
}, 100);
}
});
$( window ).bind( "orientationchange", function ( e ) {
resizePageContentHeight( $(".ui-page") );
});
}( jQuery, window, document ) );
/*!
* jQuery Templates Plugin 1.0.0pre
* http://github.com/jquery/jquery-tmpl
* Requires jQuery 1.4.2
*
* Copyright Software Freedom Conservancy, Inc.
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/
(function( jQuery, undefined ){
var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = [];
function newTmplItem( options, parentItem, fn, data ) {
// Returns a template item data structure for a new rendered instance of a template (a 'template item').
// The content field is a hierarchical array of strings and nested items (to be
// removed and replaced by nodes field of dom elements, once inserted in DOM).
var newItem = {
data: data || (data === 0 || data === false) ? data : (parentItem ? parentItem.data : {}),
_wrap: parentItem ? parentItem._wrap : null,
tmpl: null,
parent: parentItem || null,
nodes: [],
calls: tiCalls,
nest: tiNest,
wrap: tiWrap,
html: tiHtml,
update: tiUpdate
};
if ( options ) {
jQuery.extend( newItem, options, { nodes: [], parent: parentItem });
}
if ( fn ) {
// Build the hierarchical content to be used during insertion into DOM
newItem.tmpl = fn;
newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem );
newItem.key = ++itemKey;
// Keep track of new template item, until it is stored as jQuery Data on DOM element
(stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem;
}
return newItem;
}
// Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core).
jQuery.each({
appendTo: "append",
prependTo: "prepend",
insertBefore: "before",
insertAfter: "after",
replaceAll: "replaceWith"
}, function( name, original ) {
jQuery.fn[ name ] = function( selector ) {
var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems,
parent = this.length === 1 && this[0].parentNode;
appendToTmplItems = newTmplItems || {};
if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
insert[ original ]( this[0] );
ret = this;
} else {
for ( i = 0, l = insert.length; i < l; i++ ) {
cloneIndex = i;
elems = (i > 0 ? this.clone(true) : this).get();
jQuery( insert[i] )[ original ]( elems );
ret = ret.concat( elems );
}
cloneIndex = 0;
ret = this.pushStack( ret, name, insert.selector );
}
tmplItems = appendToTmplItems;
appendToTmplItems = null;
jQuery.tmpl.complete( tmplItems );
return ret;
};
});
jQuery.fn.extend({
// Use first wrapped element as template markup.
// Return wrapped set of template items, obtained by rendering template against data.
tmpl: function( data, options, parentItem ) {
return jQuery.tmpl( this[0], data, options, parentItem );
},
// Find which rendered template item the first wrapped DOM element belongs to
tmplItem: function() {
return jQuery.tmplItem( this[0] );
},
// Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
template: function( name ) {
return jQuery.template( name, this[0] );
},
domManip: function( args, table, callback, options ) {
if ( args[0] && jQuery.isArray( args[0] )) {
var dmArgs = jQuery.makeArray( arguments ), elems = args[0], elemsLength = elems.length, i = 0, tmplItem;
while ( i < elemsLength && !(tmplItem = jQuery.data( elems[i++], "tmplItem" ))) {}
if ( tmplItem && cloneIndex ) {
dmArgs[2] = function( fragClone ) {
// Handler called by oldManip when rendered template has been inserted into DOM.
jQuery.tmpl.afterManip( this, fragClone, callback );
};
}
oldManip.apply( this, dmArgs );
} else {
oldManip.apply( this, arguments );
}
cloneIndex = 0;
if ( !appendToTmplItems ) {
jQuery.tmpl.complete( newTmplItems );
}
return this;
}
});
jQuery.extend({
// Return wrapped set of template items, obtained by rendering template against data.
tmpl: function( tmpl, data, options, parentItem ) {
var ret, topLevel = !parentItem;
if ( topLevel ) {
// This is a top-level tmpl call (not from a nested template using {{tmpl}})
parentItem = topTmplItem;
tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl );
wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level
} else if ( !tmpl ) {
// The template item is already associated with DOM - this is a refresh.
// Re-evaluate rendered template for the parentItem
tmpl = parentItem.tmpl;
newTmplItems[parentItem.key] = parentItem;
parentItem.nodes = [];
if ( parentItem.wrapped ) {
updateWrapped( parentItem, parentItem.wrapped );
}
// Rebuild, without creating a new template item
return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) ));
}
if ( !tmpl ) {
return []; // Could throw...
}
if ( typeof data === "function" ) {
data = data.call( parentItem || {} );
}
if ( options && options.wrapped ) {
updateWrapped( options, options.wrapped );
}
ret = jQuery.isArray( data ) ?
jQuery.map( data, function( dataItem ) {
return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null;
}) :
[ newTmplItem( options, parentItem, tmpl, data ) ];
return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret;
},
// Return rendered template item for an element.
tmplItem: function( elem ) {
var tmplItem;
if ( elem instanceof jQuery ) {
elem = elem[0];
}
while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {}
return tmplItem || topTmplItem;
},
// Set:
// Use $.template( name, tmpl ) to cache a named template,
// where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc.
// Use $( "selector" ).template( name ) to provide access by name to a script block template declaration.
// Get:
// Use $.template( name ) to access a cached template.
// Also $( selectorToScriptBlock ).template(), or $.template( null, templateString )
// will return the compiled template, without adding a name reference.
// If templateString includes at least one HTML tag, $.template( templateString ) is equivalent
// to $.template( null, templateString )
template: function( name, tmpl ) {
if (tmpl) {
// Compile template and associate with name
if ( typeof tmpl === "string" ) {
// This is an HTML string being passed directly in.
tmpl = buildTmplFn( tmpl );
} else if ( tmpl instanceof jQuery ) {
tmpl = tmpl[0] || {};
}
if ( tmpl.nodeType ) {
// If this is a template block, use cached copy, or generate tmpl function and cache.
tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML ));
// Issue: In IE, if the container element is not a script block, the innerHTML will remove quotes from attribute values whenever the value does not include white space.
// This means that foo="${x}" will not work if the value of x includes white space: foo="${x}" -> foo=value of x.
// To correct this, include space in tag: foo="${ x }" -> foo="value of x"
}
return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl;
}
// Return named compiled template
return name ? (typeof name !== "string" ? jQuery.template( null, name ):
(jQuery.template[name] ||
// If not in map, and not containing at least on HTML tag, treat as a selector.
// (If integrated with core, use quickExpr.exec)
jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null;
},
encode: function( text ) {
// Do HTML encoding replacing < > & and ' and " by corresponding entities.
return ("" + text).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;");
}
});
jQuery.extend( jQuery.tmpl, {
tag: {
"tmpl": {
_default: { $2: "null" },
open: "if($notnull_1){__=__.concat($item.nest($1,$2));}"
// tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions)
// This means that {{tmpl foo}} treats foo as a template (which IS a function).
// Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}.
},
"wrap": {
_default: { $2: "null" },
open: "$item.calls(__,$1,$2);__=[];",
close: "call=$item.calls();__=call._.concat($item.wrap(call,__));"
},
"each": {
_default: { $2: "$index, $value" },
open: "if($notnull_1){$.each($1a,function($2){with(this){",
close: "}});}"
},
"if": {
open: "if(($notnull_1) && $1a){",
close: "}"
},
"else": {
_default: { $1: "true" },
open: "}else if(($notnull_1) && $1a){"
},
"html": {
// Unecoded expression evaluation.
open: "if($notnull_1){__.push($1a);}"
},
"=": {
// Encoded expression evaluation. Abbreviated form is ${}.
_default: { $1: "$data" },
open: "if($notnull_1){__.push($.encode($1a));}"
},
"!": {
// Comment tag. Skipped by parser
open: ""
}
},
// This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
complete: function( items ) {
newTmplItems = {};
},
// Call this from code which overrides domManip, or equivalent
// Manage cloning/storing template items etc.
afterManip: function afterManip( elem, fragClone, callback ) {
// Provides cloned fragment ready for fixup prior to and after insertion into DOM
var content = fragClone.nodeType === 11 ?
jQuery.makeArray(fragClone.childNodes) :
fragClone.nodeType === 1 ? [fragClone] : [];
// Return fragment to original caller (e.g. append) for DOM insertion
callback.call( elem, fragClone );
// Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data.
storeTmplItems( content );
cloneIndex++;
}
});
//========================== Private helper functions, used by code above ==========================
function build( tmplItem, nested, content ) {
// Convert hierarchical content into flat string array
// and finally return array of fragments ready for DOM insertion
var frag, ret = content ? jQuery.map( content, function( item ) {
return (typeof item === "string") ?
// Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM.
(tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) :
// This is a child template item. Build nested template.
build( item, tmplItem, item._ctnt );
}) :
// If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}.
tmplItem;
if ( nested ) {
return ret;
}
// top-level template
ret = ret.join("");
// Support templates which have initial or final text nodes, or consist only of text
// Also support HTML entities within the HTML markup.
ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) {
frag = jQuery( middle ).get();
storeTmplItems( frag );
if ( before ) {
frag = unencode( before ).concat(frag);
}
if ( after ) {
frag = frag.concat(unencode( after ));
}
});
return frag ? frag : unencode( ret );
}
function unencode( text ) {
// Use createElement, since createTextNode will not render HTML entities correctly
var el = document.createElement( "div" );
el.innerHTML = text;
return jQuery.makeArray(el.childNodes);
}
// Generate a reusable function that will serve to render a template against data
function buildTmplFn( markup ) {
return new Function("jQuery","$item",
// Use the variable __ to hold a string array while building the compiled template. (See https://github.com/jquery/jquery-tmpl/issues#issue/10).
"var $=jQuery,call,__=[],$data=$item.data;" +
// Introduce the data as local variables using with(){}
"with($data){__.push('" +
// Convert the template into pure JavaScript
jQuery.trim(markup)
.replace( /([\\'])/g, "\\$1" )
.replace( /[\r\t\n]/g, " " )
.replace( /\$\{([^\}]*)\}/g, "{{= $1}}" )
.replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
function( all, slash, type, fnargs, target, parens, args ) {
var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect;
if ( !tag ) {
throw "Unknown template tag: " + type;
}
def = tag._default || [];
if ( parens && !/\w$/.test(target)) {
target += parens;
parens = "";
}
if ( target ) {
target = unescape( target );
args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : "");
// Support for target being things like a.toLowerCase();
// In that case don't call with template item as 'this' pointer. Just evaluate...
expr = parens ? (target.indexOf(".") > -1 ? target + unescape( parens ) : ("(" + target + ").call($item" + args)) : target;
exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))";
} else {
exprAutoFnDetect = expr = def.$1 || "null";
}
fnargs = unescape( fnargs );
return "');" +
tag[ slash ? "close" : "open" ]
.split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" )
.split( "$1a" ).join( exprAutoFnDetect )
.split( "$1" ).join( expr )
.split( "$2" ).join( fnargs || def.$2 || "" ) +
"__.push('";
}) +
"');}return __;"
);
}
function updateWrapped( options, wrapped ) {
// Build the wrapped content.
options._wrap = build( options, true,
// Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string.
jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()]
).join("");
}
function unescape( args ) {
return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null;
}
function outerHtml( elem ) {
var div = document.createElement("div");
div.appendChild( elem.cloneNode(true) );
return div.innerHTML;
}
// Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance.
function storeTmplItems( content ) {
var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m;
for ( i = 0, l = content.length; i < l; i++ ) {
if ( (elem = content[i]).nodeType !== 1 ) {
continue;
}
elems = elem.getElementsByTagName("*");
for ( m = elems.length - 1; m >= 0; m-- ) {
processItemKey( elems[m] );
}
processItemKey( elem );
}
function processItemKey( el ) {
var pntKey, pntNode = el, pntItem, tmplItem, key;
// Ensure that each rendered template inserted into the DOM has its own template item,
if ( (key = el.getAttribute( tmplItmAtt ))) {
while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { }
if ( pntKey !== key ) {
// The next ancestor with a _tmplitem expando is on a different key than this one.
// So this is a top-level element within this template item
// Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment.
pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0;
if ( !(tmplItem = newTmplItems[key]) ) {
// The item is for wrapped content, and was copied from the temporary parent wrappedItem.
tmplItem = wrappedItems[key];
tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode] );
tmplItem.key = ++itemKey;
newTmplItems[itemKey] = tmplItem;
}
if ( cloneIndex ) {
cloneTmplItem( key );
}
}
el.removeAttribute( tmplItmAtt );
} else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) {
// This was a rendered element, cloned during append or appendTo etc.
// TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem.
cloneTmplItem( tmplItem.key );
newTmplItems[tmplItem.key] = tmplItem;
pntNode = jQuery.data( el.parentNode, "tmplItem" );
pntNode = pntNode ? pntNode.key : 0;
}
if ( tmplItem ) {
pntItem = tmplItem;
// Find the template item of the parent element.
// (Using !=, not !==, since pntItem.key is number, and pntNode may be a string)
while ( pntItem && pntItem.key != pntNode ) {
// Add this element as a top-level node for this rendered template item, as well as for any
// ancestor items between this item and the item of its parent element
pntItem.nodes.push( el );
pntItem = pntItem.parent;
}
// Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering...
delete tmplItem._ctnt;
delete tmplItem._wrap;
// Store template item as jQuery data on the element
jQuery.data( el, "tmplItem", tmplItem );
}
function cloneTmplItem( key ) {
key = key + keySuffix;
tmplItem = newClonedItems[key] =
(newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent ));
}
}
}
//---- Helper functions for template item ----
function tiCalls( content, tmpl, data, options ) {
if ( !content ) {
return stack.pop();
}
stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options });
}
function tiNest( tmpl, data, options ) {
// nested template, using {{tmpl}} tag
return jQuery.tmpl( jQuery.template( tmpl ), data, options, this );
}
function tiWrap( call, wrapped ) {
// nested template, using {{wrap}} tag
var options = call.options || {};
options.wrapped = wrapped;
// Apply the template, which may incorporate wrapped content,
return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item );
}
function tiHtml( filter, textOnly ) {
var wrapped = this._wrap;
return jQuery.map(
jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ),
function(e) {
return textOnly ?
e.innerText || e.textContent :
e.outerHTML || outerHtml(e);
});
}
function tiUpdate() {
var coll = this.nodes;
jQuery.tmpl( null, null, null, this).insertBefore( coll[0] );
jQuery( coll ).remove();
}
})( jQuery );
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* jQuery Mobile Framework : "controlbar" plugin
* Copyright (c) jQuery Project
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
* Authors: Jinhyuk Jun <jinhyuk.jun@samsung.com>
*/
/**
* Controlbar can be created using data-role = "controlbar" inside footer
* Framework determine which controlbar will display with controlbar attribute
*
* Attributes:
*
* data-style : determine which controlbar will use ( tabbar / toolbar )
* tabbar do not have back button, toolbar has back button
*
* Examples:
*
* HTML markup for creating tabbar: ( 2 ~ 5 li item available )
* icon can be changed data-icon attribute
* <div data-role="footer"data-position ="fixed">
* <div data-role="controlbar" data-style="tabbar" >
* <ul>
* <li><a href="#" data-icon="ctrlbar-menu" class="ui-btn-active">Menu</a></li>
* <li><a href="#" data-icon="ctrlbar-save" >Save</a></li>
* <li><a href="#" data-icon="ctrlbar-share" >Share</a></li>
* </ul>
* </div>
* </div>
*
* HTML markup for creating toolbar: ( 2 ~ 5 li item available )
* icon can be changed data-icon attribute
* <div data-role="footer" data-position ="fixed">
* <div data-role="controlbar" data-style="toolbar" >
* <ul>
* <li><a href="#" data-icon="ctrlbar-menu" class="ui-btn-active">Menu</a></li>
* <li><a href="#" data-icon="ctrlbar-save" >Save</a></li>
* <li><a href="#" data-icon="ctrlbar-share" >Share</a></li>
* </ul>
* </div>
* </div>
*/
(function ( $, undefined ) {
$.widget( "tizen.controlbar", $.mobile.widget, {
options: {
iconpos: "top",
grid: null,
initSelector: ":jqmData(role='controlbar')"
},
_create: function () {
var $controlbar = this.element,
$navbtns = $controlbar.find( "a" ),
iconpos = $navbtns.filter( ":jqmData(icon)" ).length ?
this.options.iconpos : undefined,
theme = $.mobile.listview.prototype.options.theme, /* Get current theme */
style = $controlbar.attr( "data-style" );
if ( style === "left" || style === "right" ) {
$controlbar
.parents( ".ui-content" )
.css( 'padding', '0' );
} else {
$controlbar
.addClass( "ui-navbar" )
.attr( "role", "navigation" )
.find( "ul" )
.grid( { grid: this.options.grid } );
}
if ( !iconpos ) {
$controlbar.addClass( "ui-navbar-noicons" );
}
$navbtns.buttonMarkup({
corners: false,
shadow: false,
iconpos: iconpos
});
$controlbar.delegate( "a", "vclick", function ( event ) {
$navbtns.not( ".ui-state-persist" ).removeClass( $.mobile.activeBtnClass );
$( this ).addClass( $.mobile.activeBtnClass );
});
if ( style === "tabbar" || style === "toolbar" ) {
$controlbar
.addClass( "ui-controlbar-" + theme )
.addClass( "ui-" + style + "-" + theme );
} else {
$controlbar
.addClass( "ui-controlbar-" + style )
.end();
}
$( document ).bind( "pagebeforeshow", function ( event, ui ) {
var footer_filter = $( event.target ).find( ":jqmData(role='footer')" ),
controlbar_filter = footer_filter.find( ":jqmData(role='controlbar')" ),
style = controlbar_filter.jqmData( "style" );
if ( style == "toolbar" || style == "tabbar" ) {
/* Need to add text only style */
if ( !(controlbar_filter.find(".ui-btn-inner").children().is(".ui-icon")) ) {
controlbar_filter.find( ".ui-btn-inner" ).addClass( "ui-navbar-textonly" );
} else {
if ( controlbar_filter.find( ".ui-btn-text" ).text() == "" ) {
controlbar_filter.find( ".ui-btn" ).addClass( "ui-ctrlbar-icononly" );
}
}
footer_filter
.css( "position", "fixed" )
.css( "height", controlbar_filter.height() )
.css( "top", window.innerHeight - footer_filter.height() );
if ( style == "toolbar" ) {
controlbar_filter
.css( "width", window.innerWidth - controlbar_filter.siblings(".ui-btn").width() );
}
}
});
$( document ).bind( "pageshow", function ( e, ui ) {
var controlbar_filter = $( ".ui-page" ).find( ":jqmData(role='footer')" ).eq( 0 ).find( ":jqmData(role='controlbar')" ),
element_count = controlbar_filter.find( 'li' ).length;
if ( controlbar_filter.find(".ui-btn-active").length == 0 ) {
controlbar_filter.find( "div" ).css( "left", "0px" );
} else {
controlbar_filter.find( "div" ).css( "left", controlbar_filter.find( ".ui-btn-active" ).parent( "li" ).index() * controlbar_filter.width() / element_count );
}
/* Increase Content size with dummy <div> because of footer height */
if ( controlbar_filter.length != 0 && $( ".ui-page-active" ).find( ".dummy-div" ).length == 0 && $( ".ui-page-active" ).find( ":jqmData(role='footer')" ).find( ":jqmData(role='controlbar')" ).length != 0 ) {
$( ".ui-page-active" ).find( ":jqmData(role='content')" ).append( '<div class="dummy-div"></div>' );
$( ".ui-page-active" ).find( ".dummy-div" )
.css( "width", controlbar_filter.width() )
.css( "height", controlbar_filter.height() );
}
});
},
_setDisabled: function ( value, cnt ) {
this.element.find( "li" ).eq( cnt ).attr( "disabled", value );
this.element.find( "li" ).eq( cnt ).attr( "aria-disabled", value );
},
disable: function ( cnt ) {
this._setDisabled( true, cnt );
this.element.find( "li" ).eq( cnt ).addClass( "ui-disabled" );
},
enable: function ( cnt ) {
this._setDisabled( false, cnt );
this.element.find( "li" ).eq( cnt ).removeClass( "ui-disabled" );
}
});
//auto self-init widgets
$( document ).bind( "pagecreate create", function ( e ) {
$( $.tizen.controlbar.prototype.options.initSelector, e.target ).controlbar();
});
}( jQuery ) );
/*global Globalize:false, range:false, regexp:false*/
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Salvatore Iovene <salvatore.iovene@intel.com>
* Daehyon Jung <darrenh.jung@samsung.com>
*/
/**
* datetimepicker is a widget that lets the user select a date and/or a
* time. If you'd prefer use as auto-initialization of form elements,
* use input elements with type=date/time/datetime within form tag
* as same as other form elements.
*
* HTML Attributes:
*
* data-role: 'datetimepicker'
* data-format: date format string. e.g) "MMM dd yyyy, HH:mm"
* type: 'date', 'datetime', 'time'
* data-val: pre-set value. any date/time string Date.parse() accepts.
*
* Options:
* type: 'date', 'datetime', 'time'
* format: see data-format in HTML Attributes.
* val: see data-val in HTML Attributes.
*
* APIs:
* getValue()
* : Get current selected date/time as W3C DTF style string.
* update()
* : Force to update fields.
*
* Events:
* data-changed: Raised when date/time was changed.
*
* Examples:
* <ul data-role="listview">
* <li class="ui-li-3-2-2">
* <span class="ui-li-text-main">
* <input type="datetime" name="demo-date" id="demo-date"
* data-format="MMM dd yyyy hh:mm tt"/>
* </span>
* <span class="ui-li-text-sub">
* Date/Time Picker - <span id="selected-date1"><em>(select a date first)</em></span>
* </span>
* </li>
* <li class="ui-li-3-2-2">
* <span class="ui-li-text-main">
* <input type="date" name="demo-date2" id="demo-date2"/>
* </span>
* <span class="ui-li-text-sub">
* Date Picker - <span id="selected-date2"><em>(select a date first)</em></span>
* </span>
* </li>
* <li class="ui-li-3-2-2">
* <span class="ui-li-text-main">
* <input type="time" name="demo-date3" id="demo-date3"/>
* </span>
* <span class="ui-li-text-sub">
* Time Picker - <span id="selected-date3"><em>(select a date first)</em></span>
* </span>
* </li>
* </ul>
* How to get a return value:
* ==========================
* Bind to the 'date-changed' event, e.g.:
* $("#myDatetimepicker").bind("date-changed", function(e, date) {
* alert("New date: " + date.toString());
* });
*/
( function ( $, window, undefined ) {
$.widget( "tizen.datetimepicker", $.tizen.widgetex, {
options: {
type: 'datetime', // date, time, datetime applicable
format: null,
val: null,
initSelector: "input[type='date'], input[type='datetime'], input[type='time'], :jqmData(role='datetimepicker')"
},
_makeTwoDigits: function ( val ) {
var ret = val.toString(10);
if ( val < 10 ) {
ret = "0" + ret;
}
return ret;
},
/**
* return W3C DTF string
*/
getValue: function () {
var data = [],
item,
greg,
obj = this,
toTimeString,
toDateString;
for ( item in this.data ) {
data[item] = this.data[item];
}
if ( this.calendar.convert ) {
greg = this.calendar.convert.toGregorian( data.year, data.month, data.day );
data.year = greg.getFullYear();
data.month = greg.getMonth();
data.day = greg.getDate();
}
obj = this;
toTimeString = function timeStr( t ) {
return obj._makeTwoDigits( t.hour ) + ':' +
obj._makeTwoDigits( t.min ) + ':' +
obj._makeTwoDigits( t.sec );
};
toDateString = function dateStr( d ) {
return ( ( d.year % 10000 ) + 10000 ).toString().substr(1) + '-' +
obj._makeTwoDigits( d.month ) + '-' +
obj._makeTwoDigits( d.day );
};
switch ( this.options.type ) {
case 'time':
return toTimeString( data );
case 'date':
return toDateString( data );
default:
return toDateString( data ) + 'T' + toTimeString( data );
}
},
_updateField: function ( target, value ) {
if ( !target || target.length == 0 ) {
return;
}
if ( value == 0 ) {
value = "0";
}
var pat = target.jqmData( 'pat' ),
hour;
switch ( pat ) {
case 'H':
case 'HH':
case 'h':
case 'hh':
hour = value;
if ( pat.charAt(0) == 'h' ) {
if ( hour > 12 ) {
hour -= 12;
} else if ( hour == 0 ) {
hour = 12;
}
}
if ( pat.length == 2 ) {
hour = this._makeTwoDigits( hour );
}
target.text( hour );
break;
case 'm':
case 'M':
case 'd':
case 's':
target.text( value );
break;
case 'mm':
case 'dd':
case 'MM':
case 'ss':
target.text( this._makeTwoDigits( value ) );
break;
case 'MMM':
target.text( this.calendar.months.namesAbbr[ value - 1] );
break;
case 'MMMM':
target.text( this.calendar.months.names[ value - 1 ] );
break;
case 'yy':
target.text( this._makeTwoDigits( value % 100 ) );
break;
case 'yyyy':
if ( value < 10 ) {
value = '000' + value;
} else if ( value < 100 ) {
value = '00' + value;
} else if ( value < 1000 ) {
value = '0' + value;
}
target.text( value );
break;
}
},
_format: function ( pattern ) {
var token = this._parsePattern( pattern ),
div = document.createElement('div'),
attr = [],
pat,
tpl,
ampm,
btn;
while ( token.length > 0 ) {
pat = token.shift();
tpl = '<span class="ui-datefield-%1" data-pat="' + pat + '">%2</span>';
switch ( pat ) {
case 'H': //0 1 2 3 ... 21 22 23
case 'HH': //00 01 02 ... 21 22 23
case 'h': //0 1 2 3 ... 11 12
case 'hh': //00 01 02 ... 11 12
$(div).append( tpl.replace('%1', 'hour') );
attr.hour = true;
break;
case 'mm': //00 01 ... 59
case 'm': //0 1 2 ... 59
$(div).append( tpl.replace('%1', 'min') );
attr.min = true;
break;
case 'ss':
case 's':
$(div).append( tpl.replace('%1', 'sec') );
attr.sec = true;
break;
case 'd': // day of month 5
case 'dd': // day of month(leading zero) 05
$(div).append( tpl.replace('%1', 'day') );
attr.day = true;
break;
case 'M': // Month of year 9
case 'MM': // Month of year(leading zero) 09
case 'MMM':
case 'MMMM':
$(div).append( tpl.replace('%1', 'month') );
attr.month = true;
break;
case 'yy': // year two digit
case 'yyyy': // year four digit
$(div).append( tpl.replace('%1', 'year') );
attr.year = true;
break;
case 't': //AM / PM indicator(first letter) A, P
// add button
case 'tt': //AM / PM indicator AM/PM
// add button
ampm = this.data.hour > 11 ?
this.calendar.PM[0] : this.calendar.AM[0];
btn = '<a href="#" class="ui-datefield-ampm"' +
' data-role="button" data-inline="true">' +
ampm + '</a>';
$(div).append( btn );
attr.ampm = true;
break;
case 'g':
case 'gg':
$(div).append( tpl.replace('%1', 'era').replace('%2', this.calendar.eras.name) );
break;
default : // string or any non-clickable object
$(div).append( tpl.replace('%1', 'seperator').replace('%2', pat) );
break;
}
}
return {
attr: attr,
html: div
};
},
_switchAmPm: function ( obj, owner ) {
if ( this.calendar.AM != null ) {
if ( this.calendar.AM[0] == $(owner).find('.ui-btn-text').text() ) { // AM to PM
this.data.hour += 12;
$(owner).find('.ui-btn-text').text( this.calendar.PM[0] );
} else { // PM to AM
this.data.hour -= 12;
$(owner).find('.ui-btn-text').text( this.calendar.AM[0] );
}
obj.update();
}
},
update: function () {
if ( $(this.elem).is('input') ) {
this.options.val = this.getValue();
this.elem.value = this.options.val;
}
$(this.elem).trigger('date-changed', this.getValue() );
},
_parsePattern: function ( pattern ) {
var regex = /^(\/|\s|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|f|gg|g)|('[\w\W\s]*?')/,
token = [],
s;
while ( pattern.length > 0 ) {
s = regex.exec( pattern );
if ( s ) {
pattern = pattern.substr( s[0].length );
if ( s[0].charAt(0) == "'" ) {
s[0] = s[0].substr( 1, s[0].length - 2 );
}
token.push( s[0] );
} else {
token.push( pattern.charAt(0) );
pattern = pattern.substr(1);
}
}
return token;
},
_create: function () {
var input = this.element.get(0),
type = $(input).attr("type"),
isTime,
isDate,
val,
now,
data,
local,
obj = this,
$div;
if ( type ) {
obj.options.type = type;
}
isTime = type.indexOf("time") > -1;
isDate = type.indexOf("date") > -1;
$.extend( obj, {
elem: input,
time: isTime,
date: isDate,
calendar: window.Globalize.culture().calendars.standard,
data: {
"hour" : 0,
"min" : 0,
"sec" : 0,
"year" : 0,
"month" : 0,
"day" : 0
}
});
// init date&time
val = this.options.val;
if ( val ) {
now = new Date( Date.parse( val ) );
} else {
now = new Date();
}
data = obj.data;
if ( isDate ) {
if ( obj.calendar.convert ) {
local = obj.calendar.convert.fromGregorian( now );
data.year = local.year;
data.month = local.month + 1;
data.day = local.day;
} else {
data.year = now.getFullYear();
data.month = now.getMonth() + 1;
data.day = now.getDate();
}
}
if ( isTime ) {
data.hour = now.getHours();
data.min = now.getMinutes();
data.sec = now.getSeconds();
}
$(input).css('display', 'none');
$div = $(document.createElement('div'));
$div.addClass('ui-datefield');
$(input).after( $div );
this._initField( this.options.type, $div );
$div.trigger('create');
$div.bind('vclick', function ( e ) {
obj._showDataSelector( obj, this, e.target );
});
$div.find('.ui-datefield-ampm').bind( 'vclick', function ( e ) {
obj._switchAmPm( obj, this );
});
},
_populateDataSelector: function ( field, pat, obj ) {
var values,
numItems,
current,
data,
range = window.range,
local,
yearlb,
yearhb,
day;
switch ( field ) {
case 'hour':
if ( pat == 'H' ) {
// twentyfour
values = range( 0, 23 );
data = range( 0, 23 );
current = obj.data.hour;
} else {
values = range( 1, 12 );
current = obj.data.hour - 1;//11
if ( current >= 11 ) {
current = current - 12;
data = range( 13, 23 );
data.push( 12 ); // consider 12:00 am as 00:00
} else {
data = range( 1, 11 );
data.push( 0 );
}
if ( current < 0 ) {
current = 11; // 12:00 or 00:00
}
}
if ( pat.length == 2 ) {
// two digit
values = values.map( obj._makeTwoDigits );
}
numItems = values.length;
break;
case 'min':
case 'sec':
values = range( 0, 59 );
if ( pat.length == 2 ) {
values = values.map( obj._makeTwoDigits );
}
data = range( 0, 59 );
current = ( field == 'min' ? obj.data.min : obj.data.sec );
numItems = values.length;
break;
case 'year':
local = new Date( 1900, 0, 1 );
if ( obj.calendar.convert ) {
local = obj.calendar.convert.fromGregorian( local );
yearlb = local.year;
yearhb = yearlb + 200;
} else {
yearlb = local.getFullYear();
yearhb = yearlb + 200;
}
data = range( yearlb, yearhb );
current = obj.data.year - yearlb;
values = range( yearlb, yearhb );
numItems = values.length;
break;
case 'month':
switch ( pat.length ) {
case 1:
values = range( 1, 12 );
break;
case 2:
values = range( 1, 12 ).map( obj._makeTwoDigits );
break;
case 3:
values = obj.calendar.months.namesAbbr.slice();
break;
case 4:
values = obj.calendar.months.names.slice();
break;
}
if ( values.length == 13 ) { // @TODO Lunar calendar support
if ( values[12] == "" ) { // to remove lunar calendar reserved space
values.pop();
}
}
data = range( 1, values.length );
current = obj.data.month - 1;
numItems = values.length;
break;
case 'day':
//@TODO max number 31 -> depends on month
day = 31;
values = range( 1, day );
if ( pat.length == 2 ) {
values = values.map( obj._makeTwoDigits );
}
data = range( 1, day );
current = obj.data.day - 1;
numItems = day;
break;
}
return {
values: values,
data: data,
numItems: numItems,
current: current
};
},
_showDataSelector: function ( obj, ui, target ) {
target = $(target);
var attr = target.attr("class"),
field = attr.match(/ui-datefield-([\w]*)/),
pat,
data,
values,
numItems,
current,
valuesData,
item,
$li,
$item,
$ul,
$div,
$ctx;
if ( !attr ) {
return;
}
if ( !field ) {
return;
}
target.not('.ui-datefield-seperator').addClass('ui-datefield-selected');
pat = target.jqmData('pat');
data = obj._populateDataSelector( field[1], pat, obj );
values = data.values;
numItems = data.numItems;
current = data.current;
valuesData = data.data;
if ( values ) {
$ul = $(document.createElement('ul'));
for ( item in values ) {
$li = $(document.createElement('li'));
$item = $(document.createElement('a'));
$item.addClass('ui-link');
$item.text( values[item] );
$item.jqmData( "val", valuesData[item] );
$li.append( $item );
$ul.append( $li );
if ( current == item ) {
$li.addClass('current');
}
}
/* TODO NEED TO REFACTORING HERE */
$div = $(document.createElement('div'));
$div.append( $ul ).appendTo( ui );
$div.addClass('ui-datetimepicker-selector');
$div.attr( 'data-transition', 'none' );
$ctx = $div.ctxpopup();
$ctx.parents('.ui-popupwindow').addClass('ui-datetimepicker');
$div.circularview();
$div.circularview( 'centerTo', '.current' );
$ctx.popupwindow( 'open',
target.offset().left + target.width() / 2 - window.pageXOffset,
target.offset().top + target.height() - window.pageYOffset );
$div.bind('closed', function ( e ) {
$div.unbind( 'closed' );
$ul.unbind( 'vclick' );
$(obj).unbind( 'update' );
$(ui).find('.ui-datefield-selected').removeClass('ui-datefield-selected');
$ctx.popupwindow( 'destroy' );
$div.remove();
});
$(obj).bind( 'update', function ( e, val ) {
$ctx.popupwindow( 'close' );
var data = $(ui).find( '.' + field[0] );
obj._updateField( $(data), val );
obj.data[ field[1] ] = val;
obj.update();
});
$ul.bind( 'vclick', function ( e ) {
if ( $(e.target).is('a') ) {
$ul.find(".current").removeClass("current");
$(e.target).parent().addClass('current');
var val = $(e.target).jqmData("val");
$(obj).trigger( 'update', val ); // close popup, unselect field
}
});
}
},
_initField: function ( type, div ) {
var date,
time,
datetime,
updateFields = function ( obj, html, attr ) {
var item;
for ( item in attr ) {
if ( attr[item] ) {
obj._updateField( $(html).find( '.ui-datefield-' + item ),
obj.data[item] );
}
}
};
if ( this.options.format ) {
datetime = this._format( this.options.format );
updateFields( this, datetime.html, datetime.attr );
div.append( datetime.html );
} else {
if ( type.match( 'date' ) ) {
date = this._format( this.calendar.patterns.d );
$(date.html).addClass('date');
updateFields( this, date.html, date.attr );
div.append( date.html );
}
if ( type.match( 'datetime' ) ) {
div.append( '<span class="ui-datefield-tab"></span>' );
}
if ( type.match( 'time' ) ) {
time = this._format( this.calendar.patterns.t );
$(time.html).addClass('time');
updateFields( this, time.html, time.attr );
div.append( time.html );
}
}
}
});
$(document).bind("pagecreate create", function ( e ) {
$($.tizen.datetimepicker.prototype.options.initSelector, e.target)
.not(":jqmData(role='none'), :jqmData(role='nojs')")
.datetimepicker();
});
} ( jQuery, this ) );
/*
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL licenses
* http://phpjs.org/functions/range
* original by: Waldo Malqui Silva
* version: 1107.2516
*/
function range( low, high, step ) {
// Create an array containing the range of integers or characters
// from low to high (inclusive)
//
// version: 1107.2516
// discuss at: http://phpjs.org/functions/range
// + original by: Waldo Malqui Silva
// * example 1: range ( 0, 12 );
// * returns 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
// * example 2: range( 0, 100, 10 );
// * returns 2: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
// * example 3: range( 'a', 'i' );
// * returns 3: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
// * example 4: range( 'c', 'a' );
// * returns 4: ['c', 'b', 'a']
var matrix = [],
inival,
endval,
plus,
walker = step || 1,
chars = false;
if (!isNaN(low) && !isNaN(high)) {
inival = low;
endval = high;
} else if (isNaN(low) && isNaN(high)) {
chars = true;
inival = low.charCodeAt(0);
endval = high.charCodeAt(0);
} else {
inival = (isNaN(low) ? 0 : low);
endval = (isNaN(high) ? 0 : high);
}
plus = ((inival > endval) ? false : true);
if (plus) {
while (inival <= endval) {
matrix.push(((chars) ? String.fromCharCode(inival) : inival));
inival += walker;
}
} else {
while (inival >= endval) {
matrix.push(((chars) ? String.fromCharCode(inival) : inival));
inival -= walker;
}
}
return matrix;
}
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Rijubrata Bhaumik <rijubrata.bhaumik@intel.com>
* Elliot Smith <elliot.smith@intel.com>
*/
// Displays a day selector element: a control group with 7 check
// boxes which can be toggled on and off.
//
// The widget can be invoked on fieldset element with
// $(element).dayselector() or by creating a fieldset element with
// data-role="dayselector". If you try to apply it to an element
// of type other than fieldset, results will be unpredictable.
//
// The default is to display the controlgroup horizontally; you can
// override this by setting data-type="vertical" on the fieldset,
// or by passing a type option to the constructor. The data-type
// attribute has precedence.
//
// If no ID is supplied for the dayselector, one will be generated
// automatically.
//
// Methods:
//
// value: Return the day numbers (0=Sunday, ..., 6=Saturday) of
// the selected checkboxes as an array.
//
// selectAll: Select all 7 days of the week by automatically "ticking"
// all of the checkboxes.
//
// Options:
//
// theme : Override the data-theme of the widget; note that the
// order of preference is: 1) set from data-theme attribute;
// 2) set from option; 3) set from closest parent data-theme;
// 4) default to 'c'
//
// type: 'horizontal' (default) or 'vertical'; specifies the type
// of controlgroup to create around the day check boxes.
//
// days: array of day names, Sunday first; defaults to English day
// names; the first letters are used as text for the checkboxes
(function ( $, window, undefined ) {
$.widget( "tizen.dayselector", $.mobile.widget, {
options: {
initSelector: 'fieldset:jqmData(role="dayselector")',
theme: null,
type: 'horizontal',
days: ['Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday']
},
defaultTheme: 'c',
_create: function () {
var days,
parentId,
i,
day,
letter,
id,
labelClass,
checkbox,
label;
this.element.addClass( 'ui-dayselector' );
this.options.type = this.element.jqmData( 'type' ) || this.options.type;
this.options.theme = this.element.jqmData( 'theme' ) ||
this.options.theme ||
this.element.closest( ':jqmData(theme)').jqmData('theme' ) ||
this.defaultTheme;
days = this.options.days;
this.element.attr( 'data-' + $.mobile.ns + 'type', this.options.type );
parentId = this.element.attr( 'id' ) ||
'dayselector' + ( new Date() ).getTime();
for ( i = 0; i < days.length; i++ ) {
day = days[i];
letter = day.slice(0, 1);
if ( window.Globalize ) {
//TODO may some modification required to support
// start week day difference upon cultures.
letter = window.Globalize.culture().calendars.standard.days.namesShort[i];
}
id = parentId + '_' + i;
labelClass = 'ui-dayselector-label-' + i;
checkbox = $( '<input type="checkbox"/>' )
.attr( 'id', id )
.attr( 'value', i );
label = $( '<label>' + letter + '</label>' )
.attr( 'for', id )
.addClass( labelClass );
this.element.append( checkbox );
this.element.append( label );
}
this.checkboxes = this.element
.find( ':checkbox' )
.checkboxradio( { theme: this.options.theme } );
this.element.controlgroup( { excludeInvisible: false } );
},
_setOption: function ( key, value ) {
if ( key === "disabled" ) {
this._setDisabled( value );
}
},
_setDisabled: function ( value ) {
$.Widget.prototype._setOption.call(this, "disabled", value);
this.element[value ? "addClass" : "removeClass"]("ui-disabled");
},
value: function () {
var values = this.checkboxes.filter( ':checked' ).map( function () {
return this.value;
} ).get();
return values;
},
selectAll: function () {
this.checkboxes
.attr( 'checked', 'checked' )
.checkboxradio( 'refresh' );
}
} ); /* End of Widget */
// auto self-init widgets
$( document ).bind( "pagebeforecreate", function ( e ) {
var elts = $( $.tizen.dayselector.prototype.options.initSelector, e.target );
elts.not( ":jqmData(role='none'), :jqmData(role='nojs')" ).dayselector();
} );
}( jQuery, this ) );
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*/
/**
* Displays vertical multi-level list.
*
* To apply, add the attribute data-expandable="true" and id="parentid" to a <li> element for parent list item
* and add the arrribute data-expanded-by="parentid" to a <li> element for child list item.
*
* HTML Attributes:
* data-expandable: Parent list item must have 'true' value for this attribute
* data-expanded-by: Child list item expanded by parent list item must have 'true' value for this attribute
* data-initial-expansion: If you want expandable list to be expanded initially, set this value as 'true'
*
* Example:
* <li data-expandable="true" id="exp1" data-initial-expansion="true">Parent</li>
* <li data-expanded-by="exp1">Child</li>
*/
( function ( $, undefined ) {
$.widget( "tizen.expandablelist", $.mobile.widget, {
options: {
initSelector: ":jqmData(expandable='true')"
},
_hide: function ( e ) {
$( e ).removeClass( 'ui-li-expand-transition-show' )
.addClass( 'ui-li-expand-transition-hide' );
},
_show: function ( e ) {
$( e ).removeClass( 'ui-li-expand-transition-hide' )
.addClass( 'ui-li-expand-transition-show' );
},
_hide_expand_img: function ( e ) {
$( e ).removeClass( 'ui-li-expandable-hidden' )
.addClass( 'ui-li-expandable-shown' );
$( e ).find( ".ui-li-expand-icon" )
.addClass( "ui-li-expanded-icon" )
.removeClass( "ui-li-expand-icon" );
},
_show_expand_img: function ( e ) {
$( e ).removeClass( 'ui-li-expandable-shown' )
.addClass( 'ui-li-expandable-hidden' );
$( e ).find( ".ui-li-expanded-icon" )
.addClass( "ui-li-expand-icon" )
.removeClass( "ui-li-expanded-icon" );
},
_set_expand_arrow: function ( self, e, parent_is_expanded ) {
if ( parent_is_expanded ) {
self._hide_expand_img( e );
} else {
self._show_expand_img( e );
}
if ( $( e[0] ).data( "expandable" ) && parent_is_expanded == false ) {
var children = $( e ).nextAll( ":jqmData(expanded-by='" + $( e ).attr( 'id' ) + "')" );
children.each( function ( idx, child ) {
self._set_expand_arrow( self, child, e.is_expanded );
} );
}
},
_toggle: function ( self, e, parent_is_expanded ) {
if ( ! parent_is_expanded ) {
self._show( e );
} else {
self._hide( e );
if ( $( e ).data( "expandable" ) && e.is_expanded == true ) {
var children = $( e ).nextAll( ":jqmData(expanded-by='" + $( e ).attr( 'id' ) + "')" );
children.each( function ( idx, child ) {
self._toggle( self, child, e.is_expanded );
} );
e.is_expanded = false;
}
}
},
_is_hidden: function ( e ) {
return ( $( e ).height( ) == 0);
},
_create: function ( ) {
var children = $( this.element ).nextAll( ":jqmData(expanded-by='" + $( this.element ).attr( 'id' ) + "')" ),
e = this.element,
self = this,
expanded = e.nextAll( ":jqmData(expanded-by='" + e[0].id + "')" ),
initial_expansion = e.data( "initial-expansion" ),
is_expanded = false,
parent_id = null;
if ( children.length == 0 ) {
return;
}
if ( initial_expansion == true ) {
parent_id = e.data( "expanded-by" );
if ( parent_id ) {
if ( $( "#" + parent_id ).is_expanded == true) {
is_expanded = true;
}
} else {
is_expanded = true;
}
}
e[0].is_expanded = is_expanded;
if ( e[0].is_expanded ) {
self._hide_expand_img( e );
$(e).append( "<div class='ui-li-expanded-icon'></div>" );
} else {
self._show_expand_img( e );
$(e).append( "<div class='ui-li-expand-icon'></div>" );
}
if ( e[0].is_expanded ) {
expanded.each( function ( i, e ) { self._show( e ); } );
} else {
expanded.each( function ( i, e ) { self._hide( e ); } );
}
expanded.addClass( "ui-li-expanded" );
e.bind( 'vclick', function ( ) {
var _is_expanded = e[0].is_expanded;
expanded.each( function ( i, e ) { self._toggle( self, e, _is_expanded ); } );
e[0].is_expanded = ! e[0].is_expanded;
self._set_expand_arrow( self, e, e[0].is_expanded );
});
}
}); // end: $.widget()
$( document ).bind( "pagecreate create", function ( e ) {
$( $.tizen.expandablelist.prototype.options.initSelector, e.target )
.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
.expandablelist( );
});
} ( jQuery ) );
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Author: Wongi Lee <wongi11.lee@samsung.com>
*/
/**
* Extendable List Widget for unlimited data.
* To support more then 1,000 items, special list widget developed.
* Fast initialize and append some element into the DOM tree repeatedly.
* DB connection and works like DB cursor.
*
* HTML Attributes:
*
* data-role: extendablelist
* data-template : jQuery.template ID that populate into extendable list. A button : a <DIV> element with "data-role : button" should be included on data-template.
* data-dbtable : DB Table name. It used as window[DB NAME]. Loaded data should be converted as window object.
* data-extenditems : Number of elements to extend at once.
*
* ID : <UL> element that has "data-role=extendablelist" must have ID attribute.
* Class : <UL> element that has "data-role=extendablelist" should have "vlLoadSuccess" class to guaranty DB loading is completed.
* tmp_load_more : Template ID for "load more" message and button.
*
*
*APIs:
*
* create ( void )
* : API to call _create method. API for AJAX or DB loading callback.
*
* recreate ( Array )
* : Update extendable list with new data array. For example, update with search result.
*
*Examples:
*
* <script id="tmp-3-1-1" type="text/x-jquery-tmpl">
* <li class="ui-li-3-1-1"><span class="ui-li-text-main">${NAME}</span></li>
* </script>
*
* <script id="tmp_load_more" type="text/x-jquery-tmpl">
* <li class="ui-li-3-1-1" style="text-align:center; margin:0 auto">
* <div data-role="button">Load ${NUM_MORE_ITEMS} more items</div>
* </li>
* </script>
*
* <ul id = "extendable_list_main" data-role="extendablelist" data-extenditems="50" data-template="tmp-3-1-1" data-dbtable="JSON_DATA">
* </ul>
*
*/
( function ( $, undefined ) {
//Keeps track of the number of lists per page UID
//This allows support for multiple nested list in the same page
//https://github.com/jquery/jquery-mobile/issues/1617
var listCountPerPage = {},
TOTAL_ITEMS = 0,
last_index = 0;
$.widget( "tizen.extendablelist", $.mobile.widget, {
options: {
theme: "s",
countTheme: "c",
headerTheme: "b",
dividerTheme: "b",
splitIcon: "arrow-r",
splitTheme: "b",
inset: false,
id: "", /* Extendable list UL elemet's ID */
extenditems: 50, /* Number of append items */
childSelector: " li", /* To support swipe list */
dbtable: "",
template : "", /* Template for each list item */
loadmore : "tmp_load_more", /* Template for "Load more" message */
scrollview: false,
initSelector: ":jqmData(role='extendablelist')"
},
_stylerMouseUp: function () {
$( this ).addClass( "ui-btn-up-s" );
$( this ).removeClass( "ui-btn-down-s" );
},
_stylerMouseDown: function () {
$( this ).addClass( "ui-btn-down-s" );
$( this ).removeClass( "ui-btn-up-s" );
},
_stylerMouseOver: function () {
$( this ).toggleClass( "ui-btn-hover-s" );
},
_stylerMouseOut: function () {
$( this ).toggleClass( "ui-btn-hover-s" );
},
_pushData: function ( template, data ) {
var o = this.options,
i = 0,
dataTable = data,
myTemplate = $( "#" + template ),
loadMoreItems = ( o.extenditems > data.length - last_index ? data.length - last_index : o.extenditems ),
htmlData;
for (i = 0; i < loadMoreItems; i++ ) {
htmlData = myTemplate.tmpl( dataTable[ i ] );
$( o.id ).append( $( htmlData ).attr( 'id', 'li_' + i ) );
last_index++;
}
/* After push data, re-style extendable list widget */
$( o.id ).trigger( "create" );
},
_loadmore: function ( event ) {
var t = this,
o = event.data,
i = 0,
dataTable = window[ o.dbtable ],
myTemplate = $( "#" + o.template ),
loadMoreItems = ( o.extenditems > dataTable.length - last_index ? dataTable.length - last_index : o.extenditems ),
htmlData,
more_items_to_load,
num_next_load_items;
/* Remove load more message */
$( "#load_more_message" ).remove();
/* Append More Items */
for ( i = 0; i < loadMoreItems; i++ ) {
htmlData = myTemplate.tmpl( dataTable[ last_index ] );
$( o.id ).append( $( htmlData ).attr( 'id', 'li_' + last_index ) );
last_index++;
}
/* Append "Load more" message on the last of list */
if ( TOTAL_ITEMS > last_index ) {
myTemplate = $( "#" + o.loadmore );
more_items_to_load = TOTAL_ITEMS - last_index;
num_next_load_items = ( o.extenditems <= more_items_to_load ) ? o.extenditems : more_items_to_load;
htmlData = myTemplate.tmpl( { NUM_MORE_ITEMS : num_next_load_items } );
$( o.id ).append( $( htmlData ).attr( 'id', "load_more_message" ) );
}
$( o.id ).trigger( "create" );
$( o.id ).extendablelist( "refresh" );
},
recreate: function ( newArray ) {
var t = this,
o = this.options;
$( o.id ).empty();
TOTAL_ITEMS = newArray.length;
t._pushData( ( o.template), newArray );
if ( o.childSelector == " ul" ) {
$( o.id + " ul" ).swipelist();
}
$( o.id ).extendablelist();
t.refresh( true );
},
_initList: function () {
var t = this,
o = this.options,
myTemplate,
more_items_to_load,
num_next_load_items,
htmlData;
/* After AJAX loading success */
o.dbtable = t.element.data( "dbtable" );
TOTAL_ITEMS = $( window[ o.dbtable ] ).size();
/* Make Gen list by template */
if ( last_index <= 0 ) {
t._pushData( ( o.template ), window[ o.dbtable ] );
/* Append "Load more" message on the last of list */
if ( TOTAL_ITEMS > last_index ) {
myTemplate = $( "#" + o.loadmore );
more_items_to_load = TOTAL_ITEMS - last_index;
num_next_load_items = ( o.extenditems <= more_items_to_load) ? o.extenditems : more_items_to_load;
htmlData = myTemplate.tmpl( { NUM_MORE_ITEMS : num_next_load_items } );
$( o.id ).append( $( htmlData ).attr( 'id', "load_more_message" ) );
$( "#load_more_message" ).live( "click", t.options, t._loadmore );
} else {
/* No more items to load */
$( "#load_more_message" ).die();
$( "#load_more_message" ).remove();
}
}
if ( o.childSelector == " ul" ) {
$( o.id + " ul" ).swipelist();
}
$( o.id ).trigger( "create" );
t.refresh( true );
},
create: function () {
var o = this.options;
/* external API for AJAX callback */
this._create( "create" );
},
_create: function ( event ) {
var t = this,
o = this.options,
$el = this.element;
// create listview markup
t.element.addClass( function ( i, orig ) {
return orig + " ui-listview ui-extendable-list-container" + ( t.options.inset ? " ui-listview-inset ui-corner-all ui-shadow " : "" );
});
o.id = "#" + $el.attr( "id" );
if ( $el.data( "extenditems" ) ) {
o.extenditems = parseInt( $el.data( "extenditems" ), 10 );
}
$( o.id ).bind( "pagehide", function (e) {
$( o.id ).empty();
});
/* Scroll view */
if ( $( ".ui-scrollview-clip" ).size() > 0) {
o.scrollview = true;
} else {
o.scrollview = false;
}
/* After DB Load complete, Init Extendable list */
if ( $( o.id ).hasClass( "elLoadSuccess" ) ) {
if ( !$( o.id ).hasClass( "elInitComplete" ) ) {
if ( $el.data( "template" ) ) {
o.template = $el.data( "template" );
/* to support swipe list, <li> or <ul> can be main node of extendable list. */
if ( $el.data( "swipelist" ) == true ) {
o.childSelector = " ul";
} else {
o.shildSelector = " li";
}
}
$( o.id ).addClass( "elInitComplete" );
}
t._initList();
}
},
destroy : function () {
var o = this.options;
$( o.id ).empty();
TOTAL_ITEMS = 0;
last_index = 0;
$( "#load_more_message" ).die();
},
_itemApply: function ( $list, item ) {
var $countli = item.find( ".ui-li-count" );
if ( $countli.length ) {
item.addClass( "ui-li-has-count" );
}
$countli.addClass( "ui-btn-up-" + ( $list.jqmData( "counttheme" ) || this.options.countTheme ) + " ui-btn-corner-all" );
// TODO class has to be defined in markup
item.find( "h1, h2, h3, h4, h5, h6" ).addClass( "ui-li-heading" ).end()
.find( "p, dl" ).addClass( "ui-li-desc" ).end()
.find( ">img:eq(0), .ui-link-inherit>img:eq(0)" ).addClass( "ui-li-thumb" ).each(function () {
item.addClass( $( this ).is( ".ui-li-icon" ) ? "ui-li-has-icon" : "ui-li-has-thumb" );
}).end()
.find( ".ui-li-aside" ).each(function () {
var $this = $( this );
$this.prependTo( $this.parent() ); //shift aside to front for css float
});
},
_removeCorners: function ( li, which ) {
var top = "ui-corner-top ui-corner-tr ui-corner-tl",
bot = "ui-corner-bottom ui-corner-br ui-corner-bl";
li = li.add( li.find( ".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb" ) );
if ( which === "top" ) {
li.removeClass( top );
} else if ( which === "bottom" ) {
li.removeClass( bot );
} else {
li.removeClass( top + " " + bot );
}
},
_refreshCorners: function ( create ) {
var $li,
$visibleli,
$topli,
$bottomli;
if ( this.options.inset ) {
$li = this.element.children( "li" );
// at create time the li are not visible yet so we need to rely on .ui-screen-hidden
$visibleli = create ? $li.not( ".ui-screen-hidden" ) : $li.filter( ":visible" );
this._removeCorners( $li );
// Select the first visible li element
$topli = $visibleli.first()
.addClass( "ui-corner-top" );
$topli.add( $topli.find( ".ui-btn-inner" ) )
.find( ".ui-li-link-alt" )
.addClass( "ui-corner-tr" )
.end()
.find( ".ui-li-thumb" )
.not( ".ui-li-icon" )
.addClass( "ui-corner-tl" );
// Select the last visible li element
$bottomli = $visibleli.last()
.addClass( "ui-corner-bottom" );
$bottomli.add( $bottomli.find( ".ui-btn-inner" ) )
.find( ".ui-li-link-alt" )
.addClass( "ui-corner-br" )
.end()
.find( ".ui-li-thumb" )
.not( ".ui-li-icon" )
.addClass( "ui-corner-bl" );
}
},
refresh: function ( create ) {
this.parentPage = this.element.closest( ".ui-page" );
this._createSubPages();
var o = this.options,
$list = this.element,
self = this,
dividertheme = $list.jqmData( "dividertheme" ) || o.dividerTheme,
listsplittheme = $list.jqmData( "splittheme" ),
listspliticon = $list.jqmData( "spliticon" ),
li = $list.children( "li" ),
counter = $.support.cssPseudoElement || !$.nodeName( $list[ 0 ], "ol" ) ? 0 : 1,
item,
itemClass,
itemTheme,
a,
last,
splittheme,
countParent,
icon,
pos,
numli;
if ( counter ) {
$list.find( ".ui-li-dec" ).remove();
}
for ( pos = 0, numli = li.length; pos < numli; pos++ ) {
item = li.eq( pos );
itemClass = "ui-li";
// If we're creating the element, we update it regardless
if ( create || !item.hasClass( "ui-li" ) ) {
itemTheme = item.jqmData( "theme" ) || o.theme;
a = item.children( "a" );
if ( a.length ) {
icon = item.jqmData( "icon" );
item.buttonMarkup({
wrapperEls: "div",
shadow: false,
corners: false,
iconpos: "right",
/* icon: a.length > 1 || icon === false ? false : icon || "arrow-r",*/
icon: false, /* Remove unnecessary arrow icon */
theme: itemTheme
});
if ( ( icon != false ) && ( a.length == 1 ) ) {
item.addClass( "ui-li-has-arrow" );
}
a.first().addClass( "ui-link-inherit" );
if ( a.length > 1 ) {
itemClass += " ui-li-has-alt";
last = a.last();
splittheme = listsplittheme || last.jqmData( "theme" ) || o.splitTheme;
last.appendTo(item)
.attr( "title", last.getEncodedText() )
.addClass( "ui-li-link-alt" )
.empty()
.buttonMarkup({
shadow: false,
corners: false,
theme: itemTheme,
icon: false,
iconpos: false
})
.find( ".ui-btn-inner" )
.append(
$( "<span />" ).buttonMarkup( {
shadow : true,
corners : true,
theme : splittheme,
iconpos : "notext",
icon : listspliticon || last.jqmData( "icon" ) || o.splitIcon
})
);
}
} else if ( item.jqmData( "role" ) === "list-divider" ) {
itemClass += " ui-li-divider ui-btn ui-bar-" + dividertheme;
item.attr( "role", "heading" );
//reset counter when a divider heading is encountered
if ( counter ) {
counter = 1;
}
} else {
itemClass += " ui-li-static ui-body-" + itemTheme;
}
}
if ( counter && itemClass.indexOf( "ui-li-divider" ) < 0 ) {
countParent = item.is( ".ui-li-static:first" ) ? item : item.find( ".ui-link-inherit" );
countParent.addClass( "ui-li-jsnumbering" )
.prepend( "<span class='ui-li-dec'>" + (counter++) + ". </span>" );
}
item.add( item.children( ".ui-btn-inner" ) ).addClass( itemClass );
self._itemApply( $list, item );
}
this._refreshCorners( create );
},
//create a string for ID/subpage url creation
_idStringEscape: function ( str ) {
return str.replace(/\W/g , "-");
},
_createSubPages: function () {
var parentList = this.element,
parentPage = parentList.closest( ".ui-page" ),
parentUrl = parentPage.jqmData( "url" ),
parentId = parentUrl || parentPage[ 0 ][ $.expando ],
parentListId = parentList.attr( "id" ),
o = this.options,
dns = "data-" + $.mobile.ns,
self = this,
persistentFooterID = parentPage.find( ":jqmData(role='footer')" ).jqmData( "id" ),
hasSubPages,
newRemove;
if ( typeof listCountPerPage[ parentId ] === "undefined" ) {
listCountPerPage[ parentId ] = -1;
}
parentListId = parentListId || ++listCountPerPage[ parentId ];
$( parentList.find( "li>ul, li>ol" ).toArray().reverse() ).each(function ( i ) {
var self = this,
list = $( this ),
listId = list.attr( "id" ) || parentListId + "-" + i,
parent = list.parent(),
nodeEls,
title = nodeEls.first().getEncodedText(),//url limits to first 30 chars of text
id = ( parentUrl || "" ) + "&" + $.mobile.subPageUrlKey + "=" + listId,
theme = list.jqmData( "theme" ) || o.theme,
countTheme = list.jqmData( "counttheme" ) || parentList.jqmData( "counttheme" ) || o.countTheme,
newPage,
anchor;
nodeEls = $( list.prevAll().toArray().reverse() );
nodeEls = nodeEls.length ? nodeEls : $( "<span>" + $.trim(parent.contents()[ 0 ].nodeValue) + "</span>" );
//define hasSubPages for use in later removal
hasSubPages = true;
newPage = list.detach()
.wrap( "<div " + dns + "role='page' " + dns + "url='" + id + "' " + dns + "theme='" + theme + "' " + dns + "count-theme='" + countTheme + "'><div " + dns + "role='content'></div></div>" )
.parent()
.before( "<div " + dns + "role='header' " + dns + "theme='" + o.headerTheme + "'><div class='ui-title'>" + title + "</div></div>" )
.after( persistentFooterID ? $( "<div " + dns + "role='footer' " + dns + "id='" + persistentFooterID + "'>" ) : "" )
.parent()
.appendTo( $.mobile.pageContainer );
newPage.page();
anchor = parent.find('a:first');
if ( !anchor.length ) {
anchor = $( "<a/>" ).html( nodeEls || title ).prependTo( parent.empty() );
}
anchor.attr( "href", "#" + id );
}).extendablelist();
// on pagehide, remove any nested pages along with the parent page, as long as they aren't active
// and aren't embedded
if ( hasSubPages &&
parentPage.is( ":jqmData(external-page='true')" ) &&
parentPage.data( "page" ).options.domCache === false ) {
newRemove = function ( e, ui ) {
var nextPage = ui.nextPage, npURL;
if ( ui.nextPage ) {
npURL = nextPage.jqmData( "url" );
if ( npURL.indexOf( parentUrl + "&" + $.mobile.subPageUrlKey ) !== 0 ) {
self.childPages().remove();
parentPage.remove();
}
}
};
// unbind the original page remove and replace with our specialized version
parentPage
.unbind( "pagehide.remove" )
.bind( "pagehide.remove", newRemove);
}
},
// TODO sort out a better way to track sub pages of the extendable listview this is brittle
childPages: function () {
var parentUrl = this.parentPage.jqmData( "url" );
return $( ":jqmData(url^='" + parentUrl + "&" + $.mobile.subPageUrlKey + "')" );
}
});
//auto self-init widgets
$( document ).bind( "pagecreate create", function ( e ) {
$( $.tizen.extendablelist.prototype.options.initSelector, e.target ).extendablelist();
});
}( jQuery ));
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Wonseop Kim ( wonseop.kim@samsung.com )
*/
/**
* 'Handler' is widget that is working in conjunction with 'scrollview'.
* 'Handler' is supporting 'scroll event( up/down )' and is indicating scroll
* position.
*
* HTML Attributes:
*
* data-handler : This attribute is indicating that whether enable.
* If you want to use, you will set 'true'.
* data-handlertheme : Set the widget theme ( optional )
*
* APIs:
*
* enableHandler ( void )
* : Get a status that whether enable.
* enableHandler ( boolean )
* : Set a status that whether enable.
*
* Events:
*
* Examples:
*
* <div data-role="content" data-scroll="y" data-handler="true">
* <ul data-role="listview">
* <li data-role="list-divider">A</li>
* <li><a href="../../docs/lists/index.html">Adam Kinkaid</a></li>
* <li><a href="../../docs/lists/index.html">Alex Wickerham</a></li>
* <li><a href="../../docs/lists/index.html">Avery Johnson</a></li>
* </ul>
* </div>
*/
( function ( $, document, undefined ) {
// The options of handler in scrollview
$.tizen.scrollview.prototype.options.handler = false;
$.tizen.scrollview.prototype.options.handlerTheme = "s";
$.extend( $.tizen.scrollview.prototype, {
enableHandler : function ( enabled ) {
if ( typeof enabled === 'undefined' ) {
return this.options.handler;
}
this.options.handler = !!enabled;
var view = this.element;
if ( this.options.handler ) {
view.find( ".ui-scrollbar" ).hide();
view.find( ".ui-handler" ).show();
} else {
view.find( ".ui-handler" ).hide();
view.find( ".ui-scrollbar" ).show();
}
},
_handlerTimer : 0
});
$( document ).delegate( ":jqmData(scroll)", "scrollviewcreate", function () {
if ( $( this ).attr( "data-" + $.mobile.ns + "scroll" ) === "none" ) {
return;
}
var self = this,
$this = $( this ),
scrollview = $this.data( "scrollview" ),
prefix = "<div class=\"ui-handler ui-handler-",
suffix = "\"><div class=\"ui-handler-track\"><div class=\"ui-handler-thumb\"></div></div></div>",
direction = scrollview.options.direction,
isHorizontal = ( scrollview.options.direction === "x" ),
_$view = scrollview._$view,
_$clip = scrollview._$clip,
handler = null,
handlerThumb = null,
viewLength = 0,
clipLength = 0,
handlerHeight = 0,
handlerMargin = 0,
trackLength = 0,
isTouchable = $.support.touch,
dragStartEvt = ( isTouchable ? "touchstart" : "mousedown" ) + ".handler",
dragMoveEvtDefault = ( isTouchable ? "touchmove" : "mousemove" ),
dragMoveEvt = dragMoveEvtDefault + ".handler",
dragStopEvt = ( isTouchable ? "touchend" : "mouseup" ) + ".handler";
if ( $this.find( ".ui-handler-thumb" ).length !== 0 || typeof direction !== "string" ) {
return;
}
$this.append( prefix + direction + suffix );
handler = $this.find( ".ui-handler" );
handlerThumb = $this.find( ".ui-handler-thumb" ).hide();
handlerHeight = ( isHorizontal ? handlerThumb.width() : handlerThumb.height() );
handlerMargin = ( isHorizontal ? parseInt( handler.css( "right" ), 10 ) : parseInt( handler.css( "bottom" ), 10 ) );
scrollview.enableHandler( scrollview.options.handler );
$.extend( self, {
moveData : null
});
// handler drag
handlerThumb.bind( dragStartEvt, {
e : handlerThumb
}, function ( event ) {
scrollview._stopMScroll();
var target = event.data.e, t = ( isTouchable ? event.originalEvent.targetTouches[0] : event );
self.moveData = {
target : target,
X : parseInt( target.css( 'left' ), 10 ) || 0,
Y : parseInt( target.css( 'top' ), 10 ) || 0,
pX : t.pageX,
pY : t.pageY
};
clipLength = ( isHorizontal ? _$clip.width() : _$clip.height() );
viewLength = ( isHorizontal ? _$view.outerWidth( true ) : _$view.outerHeight( true ) ) - clipLength;
trackLength = clipLength - handlerHeight - handlerMargin;
_$view.trigger( "scrollstart" );
event.preventDefault();
event.stopPropagation();
$( document ).bind( dragMoveEvt, function ( event ) {
var moveData = self.moveData,
handlePos = 0,
scrollPos = 0,
t = ( isTouchable ? event.originalEvent.targetTouches[0] : event );
handlePos = ( isHorizontal ? moveData.X + t.pageX - moveData.pX : moveData.Y + t.pageY - moveData.pY );
if ( handlePos < 0 ) {
handlePos = 0;
}
if ( handlePos > trackLength ) {
handlePos = trackLength;
}
scrollPos = - Math.round( handlePos / trackLength * viewLength );
$this.attr( "display", "none" );
if ( isHorizontal ) {
scrollview._setScrollPosition( scrollPos, 0 );
moveData.target.css( {
left : handlePos
});
} else {
scrollview._setScrollPosition( 0, scrollPos );
moveData.target.css( {
top : handlePos
});
}
$this.attr( "display", "inline" );
event.preventDefault();
event.stopPropagation();
}).bind( dragStopEvt, function ( event ) {
$( document ).unbind( dragMoveEvt ).unbind( dragStopEvt );
self.moveData = null;
_$view.trigger( "scrollstop" );
event.preventDefault();
});
});
$( document ).bind( dragMoveEvtDefault, function ( event ) {
var isVisible = false,
vclass = "ui-scrollbar-visible";
if ( scrollview._$vScrollBar ) {
isVisible = scrollview._$vScrollBar.hasClass( vclass );
} else if ( scrollview._$hScrollBar ) {
isVisible = scrollview._$hScrollBar.hasClass( vclass );
}
if ( isVisible || self.moveData !== null ) {
if ( handlerThumb.hasClass( "ui-handler-visible" ) ) {
_$view.trigger( "scrollupdate" );
} else {
_$view.trigger( "scrollstart" );
}
}
});
$this.bind( "scrollstart", function ( event ) {
if ( !scrollview.enableHandler() ) {
return;
}
clipLength = ( isHorizontal ? _$clip.width() : _$clip.height() );
viewLength = ( isHorizontal ? _$view.outerWidth( true ) : _$view.outerHeight( true ) ) - clipLength;
trackLength = clipLength - handlerHeight - handlerMargin;
if ( clipLength > viewLength || trackLength < ( handlerHeight * 4 / 3 ) ) {
return;
}
handlerThumb.addClass( "ui-handler-visible" );
handlerThumb.stop().fadeIn( 'fast' );
event.preventDefault();
event.stopPropagation();
}).bind( "scrollupdate", function ( event, data ) {
if ( !scrollview.enableHandler() || clipLength > viewLength || trackLength < ( handlerHeight * 4 / 3 ) ) {
return;
}
var scrollPos = scrollview.getScrollPosition(), handlerPos = 0;
handlerThumb.stop( true, true ).hide().css( "opacity", 1.0 );
if ( isHorizontal ) {
handlerPos = Math.round( scrollPos.x / viewLength * trackLength );
handlerThumb.css( "left", handlerPos );
} else {
handlerPos = Math.round( scrollPos.y / viewLength * trackLength );
handlerThumb.css( "top", handlerPos );
}
handlerThumb.show();
event.preventDefault();
event.stopPropagation();
}).bind( "scrollstop", function ( event ) {
if ( !scrollview.enableHandler() || clipLength > viewLength ) {
return;
}
scrollview._handlerTimer = setTimeout( function () {
if ( scrollview._timerID === 0 && self.moveData === null ) {
handlerThumb.removeClass( "ui-handler-visible" );
handlerThumb.stop( true, true ).fadeOut( 'fast' );
clearTimeout( scrollview._handlerTimer );
scrollview._handlerTimer = 0;
}
}, 1000 );
event.preventDefault();
});
});
} ( jQuery, document ) );
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software" ),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Gabriel Schulhof <gabriel.schulhof@intel.com>
*/
// Displays three sliders that allow the user to select the
// hue, saturation, and value for a color.
//
// To apply, add the attribute data-role="hsvpicker" to a <div>
// element inside a page. Alternatively, call hsvpicker()
// on an element (see below).
//
// Options:
//
// color: String; the initial color can be specified in html using the
// data-color="#ff00ff" attribute or when constructed
// in javascript, eg
// $( "#myhsvpicker" ).hsvpicker({ color: "#ff00ff" });
// where the html might be :
// <div id="myhsvpicker"></div>
// The color can be changed post-construction like this :
// $( "#myhsvpicker" ).hsvpicker( "option", "color", "#ABCDEF" );
// Default: "#1a8039"
//
// Events:
//
// colorchanged: Fired when the color is changed.
(function ( $, undefined ) {
$.widget( "tizen.hsvpicker", $.tizen.colorwidget, {
options: {
initSelector: ":jqmData(role='hsvpicker')"
},
_htmlProto: {
source:
$("<div><div id='hsvpicker' class='ui-hsvpicker'>" +
" <div class='hsvpicker-clrchannel-container jquery-mobile-ui-widget'>" +
" <div class='hsvpicker-arrow-btn-container'>" +
" <a href='#' class='hsvpicker-arrow-btn' data-target='hue' data-location='left' data-inline='true' data-icon='reveal-left'></a>" +
" </div>" +
" <div class='hsvpicker-clrchannel-masks-container'>" +
" <div class='hsvpicker-clrchannel-mask hsvpicker-clrchannel-mask-white'></div>" +
" <div id='hsvpicker-hue-hue' class='hsvpicker-clrchannel-mask jquery-todons-colorwidget-clrlib-hue-gradient'></div>" +
" <div id='hsvpicker-hue-mask-val' class='hsvpicker-clrchannel-mask hsvpicker-clrchannel-mask-black' data-event-source='hue'></div>" +
" <div id='hsvpicker-hue-selector' class='hsvpicker-clrchannel-selector ui-corner-all'></div>" +
" </div>" +
" <div class='hsvpicker-arrow-btn-container'>" +
" <a href='#' class='hsvpicker-arrow-btn' data-target='hue' data-location='right' data-inline='true' data-icon='reveal'></a>" +
" </div>" +
" </div>" +
" <div class='hsvpicker-clrchannel-container jquery-mobile-ui-widget'>" +
" <div class='hsvpicker-arrow-btn-container'>" +
" <a href='#' class='hsvpicker-arrow-btn' data-target='sat' data-location='left' data-inline='true' data-icon='reveal-left'></a>" +
" </div>" +
" <div class='hsvpicker-clrchannel-masks-container'>" +
" <div id='hsvpicker-sat-hue' class='hsvpicker-clrchannel-mask'></div>" +
" <div id='hsvpicker-sat-gradient' class='hsvpicker-clrchannel-mask sat-gradient'></div>" +
" <div id='hsvpicker-sat-mask-val' class='hsvpicker-clrchannel-mask hsvpicker-clrchannel-mask-black' data-event-source='sat'></div>" +
" <div id='hsvpicker-sat-selector' class='hsvpicker-clrchannel-selector ui-corner-all'></div>" +
" </div>" +
" <div class='hsvpicker-arrow-btn-container'>" +
" <a href='#' class='hsvpicker-arrow-btn' data-target='sat' data-location='right' data-inline='true' data-icon='reveal'></a>" +
" </div>" +
" </div>" +
" <div class='hsvpicker-clrchannel-container jquery-mobile-ui-widget'>" +
" <div class='hsvpicker-arrow-btn-container'>" +
" <a href='#' class='hsvpicker-arrow-btn' data-target='val' data-location='left' data-inline='true' data-icon='reveal-left'></a>" +
" </div>" +
" <div class='hsvpicker-clrchannel-masks-container'>" +
" <div class='hsvpicker-clrchannel-mask hsvpicker-clrchannel-mask-white'></div>" +
" <div id='hsvpicker-val-hue' class='hsvpicker-clrchannel-mask'></div>" +
" <div id='hsvpicker-val-gradient' class='hsvpicker-clrchannel-mask val-gradient' data-event-source='val'></div>" +
" <div id='hsvpicker-val-selector' class='hsvpicker-clrchannel-selector ui-corner-all'></div>" +
" </div>" +
" <div class='hsvpicker-arrow-btn-container'>" +
" <a href='#' class='hsvpicker-arrow-btn' data-target='val' data-location='right' data-inline='true' data-icon='reveal'></a>" +
" </div>" +
" </div>" +
"</div>" +
"</div>")
, ui: {
container: "#hsvpicker",
hue: {
eventSource: "[data-event-source='hue']",
selector: "#hsvpicker-hue-selector",
hue: "#hsvpicker-hue-hue",
valMask: "#hsvpicker-hue-mask-val"
},
sat: {
gradient: "#hsvpicker-sat-gradient",
eventSource: "[data-event-source='sat']",
selector: "#hsvpicker-sat-selector",
hue: "#hsvpicker-sat-hue",
valMask: "#hsvpicker-sat-mask-val"
},
val: {
gradient: "#hsvpicker-val-gradient",
eventSource: "[data-event-source='val']",
selector: "#hsvpicker-val-selector",
hue: "#hsvpicker-val-hue"
}
}
},
_create: function () {
var self = this,
chan,
hsvIdx,
max,
step;
this.element
.css( "display", "none" )
.after( this._ui.container );
this._ui.hue.hue.huegradient();
$.extend( this, {
dragging_hsv: [ 0, 0, 0],
selectorDraggingOffset: {
x : -1,
y : -1
},
dragging: -1
} );
this._ui.container.find( ".hsvpicker-arrow-btn" )
.buttonMarkup()
.bind( "vclick", function ( e ) {
chan = $( this).attr( "data-" + ( $.mobile.ns || "" ) + "target" );
hsvIdx = ( "hue" === chan ) ? 0 :
( "sat" === chan) ? 1 : 2;
max = ( 0 == hsvIdx ? 360 : 1 );
step = 0.05 * max;
self.dragging_hsv[hsvIdx] = self.dragging_hsv[hsvIdx] + step * ( "left" === $( this ).attr( "data-" + ( $.mobile.ns || "" ) + "location" ) ? -1 : 1);
self.dragging_hsv[hsvIdx] = Math.min( max, Math.max( 0.0, self.dragging_hsv[hsvIdx] ) );
self._updateSelectors( self.dragging_hsv );
} );
$( document )
.bind( "vmousemove", function ( event ) {
if ( self.dragging != -1 ) {
event.stopPropagation();
event.preventDefault();
}
} )
.bind( "vmouseup", function ( event ) {
self.dragging = -1;
} );
this._bindElements( "hue", 0 );
this._bindElements( "sat", 1 );
this._bindElements( "val", 2 );
},
_bindElements: function ( chan, idx ) {
var self = this;
this._ui[chan].selector
.bind( "mousedown vmousedown", function ( e ) { self._handleMouseDown( chan, idx, e, true ); } )
.bind( "vmousemove touchmove", function ( e ) { self._handleMouseMove( chan, idx, e, true ); } )
.bind( "vmouseup", function ( e ) { self.dragging = -1; } );
this._ui[chan].eventSource
.bind( "mousedown vmousedown", function ( e ) { self._handleMouseDown( chan, idx, e, false ); } )
.bind( "vmousemove touchmove", function ( e ) { self._handleMouseMove( chan, idx, e, false ); } )
.bind( "vmouseup", function ( e ) { self.dragging = -1; } );
},
_handleMouseDown: function ( chan, idx, e, isSelector ) {
var coords = $.mobile.tizen.targetRelativeCoordsFromEvent( e ),
widgetStr = ( isSelector ? "selector" : "eventSource" );
if ( coords.x >= 0 && coords.x <= this._ui[chan][widgetStr].outerWidth() &&
coords.y >= 0 && coords.y <= this._ui[chan][widgetStr].outerHeight() ) {
this.dragging = idx;
if ( isSelector ) {
this.selectorDraggingOffset.x = coords.x;
this.selectorDraggingOffset.y = coords.y;
}
this._handleMouseMove( chan, idx, e, isSelector, coords );
}
},
_handleMouseMove: function ( chan, idx, e, isSelector, coords ) {
if ( this.dragging === idx ) {
coords = ( coords || $.mobile.tizen.targetRelativeCoordsFromEvent( e ) );
var factor = ( ( 0 === idx ) ? 360 : 1 ),
potential = ( isSelector
? ( ( this.dragging_hsv[idx] / factor) +
( ( coords.x - this.selectorDraggingOffset.x ) / this._ui[chan].eventSource.width() ) )
: ( coords.x / this._ui[chan].eventSource.width() ) );
this.dragging_hsv[idx] = Math.min( 1.0, Math.max( 0.0, potential ) ) * factor;
if ( !isSelector ) {
this.selectorDraggingOffset.x = Math.ceil( this._ui[chan].selector.outerWidth() / 2.0 );
this.selectorDraggingOffset.y = Math.ceil( this._ui[chan].selector.outerHeight() / 2.0 );
}
this._updateSelectors( this.dragging_hsv );
e.stopPropagation();
e.preventDefault();
}
},
_updateSelectors: function ( hsv ) {
var clrlib = $.tizen.colorwidget.clrlib,
clrwidget = $.tizen.colorwidget.prototype,
clr = clrlib.HSVToHSL( hsv ),
hclr = clrlib.HSVToHSL( [hsv[0], 1.0, 1.0] ),
vclr = clrlib.HSVToHSL( [hsv[0], hsv[1], 1.0] );
this._ui.hue.selector.css( { left : this._ui.hue.eventSource.width() * hsv[0] / 360} );
clrwidget._setElementColor.call( this, this._ui.hue.selector, clr, "background" );
if ( $.mobile.browser.ie ) {
this._ui.hue.hue.find( "*" ).css( "opacity", hsv[1] );
} else {
this._ui.hue.hue.css( "opacity", hsv[1] );
}
this._ui.hue.valMask.css( "opacity", 1.0 - hsv[2] );
this._ui.sat.selector.css( { left : this._ui.sat.eventSource.width() * hsv[1]} );
clrwidget._setElementColor.call( this, this._ui.sat.selector, clr, "background" );
clrwidget._setElementColor.call( this, this._ui.sat.hue, hclr, "background" );
this._ui.sat.valMask.css( "opacity", 1.0 - hsv[2] );
this._ui.val.selector.css( { left : this._ui.val.eventSource.width() * hsv[2]} );
clrwidget._setElementColor.call( this, this._ui.val.selector, clr, "background" );
clrwidget._setElementColor.call( this, this._ui.val.hue, vclr, "background" );
clrwidget._setColor.call( this, clrlib.RGBToHTML( clrlib.HSLToRGB(clr) ) );
},
_setDisabled: function ( value ) {
$.tizen.widgetex.prototype._setDisabled.call( this, value );
this._ui.container[value ? "addClass" : "removeClass"]( "ui-disabled" );
this._ui.hue.hue.huegradient( "option", "disabled", value );
$.tizen.colorwidget.prototype._displayDisabledState.call( this, this._ui.container );
},
_setColor: function ( clr ) {
if ( $.tizen.colorwidget.prototype._setColor.call( this, clr ) ) {
this.dragging_hsv = $.tizen.colorwidget.clrlib.RGBToHSV( $.tizen.colorwidget.clrlib.HTMLToRGB( this.options.color ) );
this._updateSelectors( this.dragging_hsv );
}
}
} );
$( document ).bind( "pagecreate create", function ( e ) {
$( $.tizen.hsvpicker.prototype.options.initSelector, e.target )
.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
.hsvpicker();
} );
}( jQuery ) );
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Author: Minkyu Kang <mk7.kang@samsung.com>
*/
/*
* Notification widget
*
* HTML Attributes
*
* data-role: set to 'imageslider'
* data-start-index: start index
* data-vertical-align: set to top or middle or bottom.
*
* APIs
*
* add(image_file): add the image (parameter: url of iamge)
* del(image_index): delete the image (parameter: index of image)
* refresh(): refresh the widget, should be called after add or del.
*
* Events
*
* N/A
*
* Example
*
* <div data-role="imageslider" id="imageslider" data-start-index="3" data-vertical-align="middle">
* <img src="01.jpg">
* <img src="02.jpg">
* <img src="03.jpg">
* <img src="04.jpg">
* <img src="05.jpg">
* </div>
*
*
* $('#imageslider-add').bind('vmouseup', function ( e ) {
* $('#imageslider').imageslider('add', '9.jpg');
* $('#imageslider').imageslider('add', '10.jpg');
* $('#imageslider').imageslider('refresh');
* });
*
* $('#imageslider-del').bind('vmouseup', function ( e ) {
* $('#imageslider').imageslider('del');
* });
*
*/
(function ( $, window, undefined ) {
$.widget( "tizen.imageslider", $.mobile.widget, {
options: {
photoFlicking: false
},
dragging: false,
moving: false,
max_width: 0,
max_height: 0,
org_x: 0,
org_time: null,
cur_img: null,
prev_img: null,
next_img: null,
images: [],
images_hold: [],
index: 0,
align_type: null,
direction: 1,
container: null,
interval: null,
_resize: function ( obj ) {
var width,
height,
margin = 40,
ratio,
img_max_width = this.max_width - margin,
img_max_height = this.max_height - margin;
height = obj.height();
width = obj.width();
ratio = height / width;
if ( width > img_max_width ) {
obj.width( img_max_width );
obj.height( img_max_width * ratio );
}
height = obj.height();
if ( height > img_max_height ) {
obj.height( img_max_height );
obj.width( img_max_height / ratio );
}
},
_align: function ( obj, img ) {
var img_top = 0;
if ( !obj.length ) {
return;
}
if ( this.align_type == "middle" ) {
img_top = ( this.max_height - img.height() ) / 2;
} else if ( this.align_type == "bottom" ) {
img_top = this.max_height - img.height();
} else {
img_top = 0;
}
obj.css( 'top', img_top + 'px' );
},
_detach: function ( image_index, obj ) {
if ( !obj.length ) {
return;
}
if ( image_index < 0 ) {
return;
}
if ( image_index >= this.images.length ) {
return;
}
this.images[image_index].detach();
obj.css( "display", "none" );
},
_attach: function ( image_index, obj ) {
if ( !obj.length ) {
return;
}
if ( image_index < 0 ) {
return;
}
if ( image_index >= this.images.length ) {
return;
}
obj.css( "display", "block" );
obj.append( this.images[image_index] );
this._resize( this.images[image_index] );
this._align( obj, this.images[image_index] );
},
_drag: function ( _x ) {
var delta,
coord_x;
if ( !this.dragging ) {
return;
}
if ( this.options.photoFlicking === false ) {
delta = this.org_x - _x;
// first image
if ( delta < 0 && !this.prev_img.length ) {
return;
}
// last image
if ( delta > 0 && !this.next_img.length ) {
return;
}
}
coord_x = _x - this.org_x;
this.cur_img.css( 'left', coord_x + 'px' );
if ( this.next_img.length ) {
this.next_img.css( 'left', coord_x + this.max_width + 'px' );
}
if ( this.prev_img.length ) {
this.prev_img.css( 'left', coord_x - this.max_width + 'px' );
}
},
_move: function ( _x ) {
var delta = this.org_x - _x,
flip = 0,
date,
drag_time,
sec,
self;
if ( delta == 0 ) {
return;
}
if ( delta > 0 ) {
flip = delta < ( this.max_width * 0.45 ) ? 0 : 1;
} else {
flip = -delta < ( this.max_width * 0.45 ) ? 0 : 1;
}
if ( !flip ) {
date = new Date();
drag_time = date.getTime() - this.org_time;
if ( Math.abs( delta ) / drag_time > 1 ) {
flip = 1;
}
}
if ( flip ) {
if ( delta > 0 && this.next_img.length ) {
/* next */
this._detach( this.index - 1, this.prev_img );
this.prev_img = this.cur_img;
this.cur_img = this.next_img;
this.next_img = this.next_img.next();
this.index++;
if ( this.next_img.length ) {
this.next_img.css( 'left', this.max_width + 'px' );
this._attach( this.index + 1, this.next_img );
}
this.direction = 1;
} else if ( delta < 0 && this.prev_img.length ) {
/* prev */
this._detach( this.index + 1, this.next_img );
this.next_img = this.cur_img;
this.cur_img = this.prev_img;
this.prev_img = this.prev_img.prev();
this.index--;
if ( this.prev_img.length ) {
this.prev_img.css( 'left', -this.max_width + 'px' );
this._attach( this.index - 1, this.prev_img );
}
this.direction = -1;
}
}
sec = 500;
self = this;
this.moving = true;
this.interval = setInterval( function () {
self.moving = false;
clearInterval( self.interval );
}, sec - 50 );
this.cur_img.animate( { left: 0 }, sec );
if ( this.next_img.length ) {
this.next_img.animate( { left: this.max_width }, sec );
}
if ( this.prev_img.length ) {
this.prev_img.animate( { left: -this.max_width }, sec );
}
},
_add_event: function () {
var self = this,
date;
this.container.bind( 'vmousemove', function ( e ) {
e.preventDefault();
if ( self.moving ) {
return;
}
if ( !self.dragging ) {
return;
}
self._drag( e.pageX );
} );
this.container.bind( 'vmousedown', function ( e ) {
e.preventDefault();
if ( self.moving ) {
return;
}
self.dragging = true;
self.org_x = e.pageX;
date = new Date();
self.org_time = date.getTime();
} );
this.container.bind( 'vmouseup', function ( e ) {
if ( self.moving ) {
return;
}
self.dragging = false;
self._move( e.pageX );
} );
this.container.bind( 'vmouseout', function ( e ) {
if ( self.moving ) {
return;
}
if ( !self.dragging ) {
return;
}
if ( ( e.pageX < 20 ) ||
( e.pageX > ( self.max_width - 20 ) ) ) {
self._move( e.pageX );
self.dragging = false;
}
} );
},
_del_event: function () {
this.container.unbind( 'vmousemove' );
this.container.unbind( 'vmousedown' );
this.container.unbind( 'vmouseup' );
this.container.unbind( 'vmouseout' );
},
_show: function () {
this.cur_img = $( 'div' ).find( '.ui-imageslider-bg:eq(' + this.index + ')' );
this.prev_img = this.cur_img.prev();
this.next_img = this.cur_img.next();
this._attach( this.index - 1, this.prev_img );
this._attach( this.index, this.cur_img );
this._attach( this.index + 1, this.next_img );
if ( this.prev_img.length ) {
this.prev_img.css( 'left', -this.max_width + 'px' );
}
this.cur_img.css( 'left', '0px' );
if ( this.next_img.length ) {
this.next_img.css( 'left', this.max_width + 'px' );
}
},
show: function () {
this._show();
this._add_event();
},
_hide: function () {
this._detach( this.index - 1, this.prev_img );
this._detach( this.index, this.cur_img );
this._detach( this.index + 1, this.next_img );
},
hide: function () {
this._hide();
this._del_event();
},
_get_height: function () {
var $page = $( '.ui-page' ),
$content = $page.children( '.ui-content' ),
$header = $page.children( '.ui-header' ),
$footer = $page.children( '.ui-footer' ),
header_h = $header.outerHeight(),
footer_h = $footer.outerHeight(),
padding = parseFloat( $content.css( 'padding-top' ) ) + parseFloat( $content.css( 'padding-bottom' ) ),
content_h = $( window ).height() - header_h - footer_h - padding * 2;
return content_h;
},
_create: function () {
var temp_img,
start_index,
i = 0;
$( this.element ).wrapInner( '<div class="ui-imageslider"></div>' );
$( this.element ).find( 'img' ).wrap( '<div class="ui-imageslider-bg"></div>' );
this.container = $( this.element ).find('.ui-imageslider');
this.max_width = $( window ).width();
this.max_height = this._get_height();
this.container.css( 'height', this.max_height );
temp_img = $( 'div' ).find( '.ui-imageslider-bg:first' );
while ( temp_img.length ) {
this.images[i] = temp_img.find( 'img' );
temp_img = temp_img.next();
i++;
}
for ( i = 0; i < this.images.length; i++ ) {
this.images[i].detach();
}
start_index = parseInt( $( this.element ).attr( 'data-start-index' ), 10 );
if ( start_index === undefined ) {
start_index = 0;
}
if ( start_index < 0 ) {
start_index = 0;
}
if ( start_index >= this.images.length ) {
start_index = this.images.length - 1;
}
this.index = start_index;
this.align_type = $( this.element ).attr( 'data-vertical-align' );
},
_update: function () {
var image_file,
bg_html,
temp_img;
while ( this.images_hold.length ) {
image_file = this.images_hold.shift();
bg_html = $( '<div class="ui-imageslider-bg"></div>' );
temp_img = $( '<img src="' + image_file + '"></div>' );
bg_html.append( temp_img );
this.container.append( bg_html );
this.images.push( temp_img );
}
},
refresh: function ( start_index ) {
this._update();
this._hide();
if ( start_index === undefined ) {
start_index = this.index;
}
if ( start_index < 0 ) {
start_index = 0;
}
if ( start_index >= this.images.length ) {
start_index = this.images.length - 1;
}
this.index = start_index;
this._show();
},
add: function ( image_file ) {
this.images_hold.push( image_file );
},
del: function ( image_index ) {
var temp_img;
if ( image_index === undefined ) {
image_index = this.index;
}
if ( image_index < 0 || image_index >= this.images.length ) {
return;
}
if ( image_index == this.index ) {
temp_img = this.cur_img;
if ( this.index == 0 ) {
this.direction = 1;
} else if ( this.index == this.images.length - 1 ) {
this.direction = -1;
}
if ( this.direction < 0 ) {
this.cur_img = this.prev_img;
this.prev_img = this.prev_img.prev();
if ( this.prev_img.length ) {
this.prev_img.css( 'left', -this.max_width );
this._attach( image_index - 2, this.prev_img );
}
this.index--;
} else {
this.cur_img = this.next_img;
this.next_img = this.next_img.next();
if ( this.next_img.length ) {
this.next_img.css( 'left', this.max_width );
this._attach( image_index + 2, this.next_img );
}
}
this.cur_img.animate( { left: 0 }, 500 );
} else if ( image_index == this.index - 1 ) {
temp_img = this.prev_img;
this.prev_img = this.prev_img.prev();
if ( this.prev_img.length ) {
this.prev_img.css( 'left', -this.max_width );
this._attach( image_index - 1, this.prev_img );
}
this.index--;
} else if ( image_index == this.index + 1 ) {
temp_img = this.next_img;
this.next_img = this.next_img.next();
if ( this.next_img.length ) {
this.next_img.css( 'left', this.max_width );
this._attach( image_index + 1, this.next_img );
}
} else {
temp_img = $( 'div' ).find( '.ui-imageslider-bg:eq(' + image_index + ')' );
}
this.images.splice( image_index, 1 );
temp_img.detach();
}
}); /* End of widget */
// auto self-init widgets
$( document ).bind( "pagecreate", function ( e ) {
$( e.target ).find( ":jqmData(role='imageslider')" ).imageslider();
});
$( document ).bind( "pageshow", function ( e ) {
$( e.target ).find( ":jqmData(role='imageslider')" ).imageslider( 'show' );
});
$( document ).bind( "pagebeforehide", function ( e ) {
$( e.target ).find( ":jqmData(role='imageslider')" ).imageslider( 'hide' );
} );
}( jQuery, this ) );
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Elliot Smith <elliot.smith@intel.com>
*/
// Horizontal/vertical box layout extension.
//
// This will arrange the child elements of a container in a horizontal
// or vertical row. This only makes sense if your container is a div
// and contains children which are also divs; the children should
// also have a height and width set in CSS, otherwise the layout
// manager won't know what to do with them.
//
// Apply it by setting data-layout="hbox" or data-layout="vbox" (vertical
// on a container element or calling $(element).layouthbox() or
// $(element).layoutvbox().
//
// Usually, you would use a div as the container to get the right effect
// (an element with display:block).
//
// Options can be set programmatically:
//
// $(element).layouthbox('option', 'scrollable', false)
// $(element).layoutvbox('option', 'scrollable', false)
//
// or via a data-layout-options attribute on the container:
//
// <div data-layout="hbox" data-layout-options='{"hgap":5}'>
// <div>child 1</div>
// <div>child 2</div>
// </div>
//
// <div data-layout="vbox" data-layout-options='{"vgap":5}'>
// <div>child 1</div>
// <div>child 2</div>
// </div>
//
// If you change any options after creating the widget, call
// $(element).layout*box('refresh') to have them picked up.
// However, note that it's currently not feasible to turn off scrolling
// once it's on (as calling scrollview('destroy') doesn't remove the
// scrollview custom mouse handlers).
//
// There is one major difference between the horizontal and
// vertical box layouts: if scrollable=false, the horizontal layout
// will clip children which overflow the edge of the parent container;
// by comparison, the vertical container will grow vertically to
// accommodate the height of its children. This mirrors the behaviour
// of jQuery Mobile, where elements only ever expand horizontally
// to fill the width of the window; but will expand vertically forever,
// unless the page height is artificially constrained.
//
// Options:
//
// {Integer} hgap (default=0)
// Horizontal gap (in pixels) between the child elements. Only has
// an effect on hbox.
//
// {Integer} vgap (default=0)
// Vertical gap (in pixels) between the child elements. Only has
// an effect on vbox.
//
// {Boolean} scrollable (default=true; can only be set at create time)
// Set to true to enable a scrollview on the
// container. If false, children will be clipped if
// they fall outside the edges of the container after
// layouting.
//
// {Boolean} showScrollBars (default=true)
// Set to false to hide scrollbars on the container's scrollview.
// Has no effect is scrollable=false
(function ( $, undefined ) {
// hbox
$.widget( "tizen.layouthbox", $.tizen.jlayoutadaptor, {
fixed: {
type: 'flexGrid',
rows: 1,
direction: 'x',
initSelector: ':jqmData(layout="hbox")'
},
_create: function () {
if ( !this.options.hgap ) {
this.options.hgap = 0;
}
$.tizen.jlayoutadaptor.prototype._create.apply( this, arguments );
}
} );
$( document ).bind( "pagecreate", function ( e ) {
$( $.tizen.layouthbox.prototype.fixed.initSelector, e.target )
.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
.layouthbox();
} );
// vbox
$.widget( "tizen.layoutvbox", $.tizen.jlayoutadaptor, {
fixed: {
type: 'flexGrid',
columns: 1,
direction: 'y',
initSelector: ':jqmData(layout="vbox")'
},
_create: function () {
if ( !this.options.vgap ) {
this.options.vgap = 0;
}
$.tizen.jlayoutadaptor.prototype._create.apply( this, arguments );
}
} );
$( document ).bind( "pagecreate", function ( e ) {
$( $.tizen.layoutvbox.prototype.fixed.initSelector, e.target )
.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
.layoutvbox();
} );
}( jQuery ) );
/*
* jQuery Mobile Widget @VERSION - listview controls
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (C) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Elliot Smith <elliot.smith@intel.com>
*/
// This extension supplies API to toggle the "mode" in which a list
// is displayed. The modes available is configurable, but defaults
// to ['edit', 'view']. A list can also have a control panel associated
// with it. The visibility of the control panel is governed by the current
// mode (by default, it is visible in 'edit' mode); elements within
// the listview can also be marked up to be visible in one or more of the
// available modes.
//
// One example use case would be a control panel with a "Select all" checkbox
// which, when clicked, selects all of the checkboxes in the associated
// listview items.
//
// The control panel itself should be defined as a form element.
// By default, the control panel will be hidden when the listview is
// initialised, unless you supply mode="edit" as a
// data-listview-controls option (when using the default modes). If you
// want the control panel to be visible in some mode other than
// the default, use a data-listviewcontrols-show-in="<mode>" attribute
// on the control panel element.
//
// Example usage (using the default 'edit' and 'view' modes):
//
// <!-- this is the controls element, displayed in 'edit' mode by default -->
// <form id="listviewcontrols-control-panel">
// <fieldset data-role="controlgroup">
// <input type="checkbox" id="listviewcontrols-demo-checkbox-uber" />
// <label for="listviewcontrols-demo-checkbox-uber">Select all</label>
// </fieldset>
// </form>
//
// <!-- this is the list associated with the controls -->
// <ul data-role="listview" data-listviewcontrols="#listviewcontrols-control-panel">
//
// <li>
//
// <!-- this element is only visible in 'edit' mode -->
// <fieldset data-role="controlgroup" data-listviewcontrols-show-in="edit">
// <input type="checkbox" id="listviewcontrols-demo-checkbox-1" />
// <label for="listviewcontrols-demo-checkbox-1">Greg</label>
// </fieldset>
//
// <!-- this element is only visible in 'view' mode -->
// <span data-listviewcontrols-show-in="view">Greg</span>
//
// </li>
//
// ... more li elements marked up the same way ...
//
// </ul>
//
// To associate the listview with the control panel, add
// data-listviewcontrols="..selector.." to a listview, where
// selector selects a single element (the control panel
// you defined). You can then call
// listviewcontrols('option', 'mode', '<mode>') on the
// listview to set the mode.
//
// Inside the listview's items, add controls to each item
// which are only visible when in one of the modes. To do this,
// add form elements (e.g. checkboxes) to the items as you see fit. Then,
// mark each form element with data-listviewcontrols-show-in="<mode>".
// The control's visibility now depends on the mode of the listviewcontrols:
// it is only shown when its <mode> setting matches the current mode
// of the listviewcontrols widget. You are responsible for properly
// styling the form elements inside the listview so the listview looks
// correct when they are hidden or visible.
//
// The control panel (by default, visible when in "show" mode) is flexible
// and can contain any valid form elements (or other jqm components). It's
// up to you to define the behaviour associated with interactions on
// the control panel and/or controls inside list items.
//
// Methods:
//
// visibleListItems
// Returns a jQuery object containing all the li elements in the
// listview which are currently visible and not dividers. (This
// is just a convenience to make operating on the list as a whole
// slightly simpler.)
//
// Options (set in options hash passed to constructor, or via the
// option method, or declaratively by attribute described below):
//
// controlPanelSelector {String}
// Selector string for selecting the element representing the
// control panel for the listview. The context for find() is the
// document (to give the most flexibility), so your selector
// should be specific. Set declaratively with
// data-listviewcontrols="...selector...".
//
// modesAvailable {String[]; default=['edit', 'view']}
// An array of the modes available for these controls.
//
// mode {String; default='view'}
// Current mode for the widget, which governs the visibility
// of the listview control panel and any elements marked
// with data-listviewcontrols-show-in="<mode>".
// Set declaratively with
// data-listviewcontrols-options='{"mode":"<mode>"}'.
//
// controlPanelShowIn {String; default=modesAvailable[0]}
// The mode in which the control panel is visible; defaults to the
// first element of modesAvailable. Can be set declaratively
// on the listview controls element with
// data-listviewcontrols-show-in="<mode>"
(function ($) {
$.widget( "todons.listviewcontrols", $.mobile.widget, {
_defaults: {
controlPanelSelector: null,
modesAvailable: ['edit', 'view'],
mode: 'view',
controlPanelShowIn: null
},
_listviewCssClass: 'ui-listviewcontrols-listview',
_controlsCssClass: 'ui-listviewcontrols-panel',
_create: function () {
var self = this,
o = this.options,
optionsValid = true,
page = this.element.closest( '.ui-page' ),
controlPanelSelectorAttr = 'data-' + $.mobile.ns + 'listviewcontrols',
controlPanelSelector = this.element.attr( controlPanelSelectorAttr ),
dataOptions = this.element.jqmData( 'listviewcontrols-options' ),
controlPanelShowInAttr;
o.controlPanelSelector = o.controlPanelSelector || controlPanelSelector;
// precedence for options: defaults < jqmData attribute < options arg
o = $.extend( {}, this._defaults, dataOptions, o );
optionsValid = ( this._validOption( 'modesAvailable', o.modesAvailable, o ) &&
this._validOption( 'controlPanelSelector', o.controlPanelSelector, o ) &&
this._validOption( 'mode', o.mode, o ) );
if ( !optionsValid ) {
return false;
}
// get the controls element
this.controlPanel = $( document ).find( o.controlPanelSelector ).first();
if ( this.controlPanel.length === 0 ) {
return false;
}
// once we have the controls element, we may need to override the
// mode in which controls are shown
controlPanelShowInAttr = this.controlPanel.jqmData( 'listviewcontrols-show-in' );
if ( controlPanelShowInAttr ) {
o.controlPanelShowIn = controlPanelShowInAttr;
} else if ( !o.controlPanelShowIn ) {
o.controlPanelShowIn = o.modesAvailable[0];
}
if ( !this._validOption( 'controlPanelShowIn', o.controlPanelShowIn, o ) ) {
return;
}
// done setting options
this.options = o;
// mark the controls and the list with a class
this.element.removeClass(this._listviewCssClass).addClass(this._listviewCssClass);
this.controlPanel.removeClass(this._controlsCssClass).addClass(this._controlsCssClass);
// show the widget
if ( page && !page.is( ':visible' ) ) {
page.bind( 'pageshow', function () { self.refresh(); } );
} else {
this.refresh();
}
},
_validOption: function ( varName, value, otherOptions ) {
var ok = false,
i = 0;
if ( varName === 'mode' ) {
ok = ( $.inArray( value, otherOptions.modesAvailable ) >= 0 );
} else if ( varName === 'controlPanelSelector' ) {
ok = ( $.type( value ) === 'string' );
} else if ( varName === 'modesAvailable' ) {
ok = ( $.isArray( value ) && value.length > 1 );
if ( ok ) {
for ( i = 0; i < value.length; i++ ) {
if ( value[i] === '' || $.type( value[i] ) !== 'string' ) {
ok = false;
}
}
}
} else if ( varName === 'controlPanelShowIn' ) {
ok = ( $.inArray( value, otherOptions.modesAvailable ) >= 0 );
}
return ok;
},
_setOption: function ( varName, value ) {
var oldValue = this.options[varName];
if ( oldValue !== value && this._validOption( varName, value, this.options ) ) {
this.options[varName] = value;
this.refresh();
}
},
visibleListItems: function () {
return this.element.find( 'li:not(:jqmData(role=list-divider)):visible' );
},
refresh: function () {
var self = this,
triggerUpdateLayout = false,
isVisible = null,
showIn,
modalElements;
// hide/show the control panel and hide/show controls inside
// list items based on their "show-in" option
isVisible = this.controlPanel.is( ':visible' );
if ( this.options.mode === this.options.controlPanelShowIn ) {
this.controlPanel.show();
} else {
this.controlPanel.hide();
}
if ( this.controlPanel.is( ':visible' ) !== isVisible ) {
triggerUpdateLayout = true;
}
// we only operate on elements inside list items which aren't dividers
modalElements = this.element
.find( 'li:not(:jqmData(role=list-divider))' )
.find( ':jqmData(listviewcontrols-show-in)' );
modalElements.each(function () {
showIn = $( this ).jqmData( 'listviewcontrols-show-in' );
isVisible = $( this ).is( ':visible' );
if ( showIn === self.options.mode ) {
$( this ).show();
} else {
$( this ).hide();
}
if ( $( this ).is( ':visible' ) !== isVisible ) {
triggerUpdateLayout = true;
}
} );
if ( triggerUpdateLayout ) {
this.element.trigger( 'updatelayout' );
}
}
} );
$( 'ul' ).live( 'listviewcreate', function () {
var list = $(this);
if ( list.is( ':jqmData(listviewcontrols)' ) ) {
list.listviewcontrols();
}
} );
}( jQuery ) );
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Author: Kangsik Kim <kangsik81.kim@samsung.com>
*/
/**
* Multibuttonentry widget is a kind of button widget.
* When a user inputs a text and the text gets an change event,
* the text can be changed from it to a button widget.
*
* HTML Attributes:
*
* data-listUrl : This attribute is represent a 'id' about page.
* This page is containing prepared data for provide to user.
* For example, like address book.
* data-label: This attribute is providing label for user-guide. (Default : 'To : ')
* data-descMessage : This attribute is managing message format.
* This message is displayed when widget status was changed to 'focusout'.
*
* APIs:
*
* inputtext ( void )
* : Get a string from inputbox.
* inputtext ( [string] )
* : If argument is not exist, will get a string from inputbox.
* If argument is exist, will set a string to inputbox.
* select ( [number] )
* : If argument is not exist, will act as a getter.
* Get a string of selected block.
* If widget is not exist a selected button, it will return 'null'.
* Select a button located on the index. (number : index of button)
* add ( text, [number] )
* : If second argument is not exist, will insert to a new textblock at last position.
* Insert a new button at position that is pointed by index. (number : index of button)
* remove ( [number] )
* : If argument is not exist, will remove all buttons.
* Remove a button that is pointed by index. (number : index of button)
* length ( void )
* : Get a number of buttons.
* foucsIn ( void )
* : This method change a status to 'focusin'.
* This status is able to manage a widget.
* focusOut ( void )
* : This method change a status to 'focusout'.
* This status is not able to manage a widget.
*
*
* Events:
*
* select : This event will occur when select a button.
* add : This event will occur when insert new button.
* remove : This event will occur when remove a button.
*
* Examples:
*
* <div data-role="multibuttonentry" data-label="To : " data-listUrl:"#addressbook" data-descMessage="{0} & {1} more...">
* </div>
*
*/
( function ( $, window, document, undefined ) {
$.widget( "tizen.multibuttonentry", $.mobile.widget, {
_focusStatus : null,
_items : null,
_viewWidth : 0,
_reservedWidth : 0,
_currentWidth : 0,
_fontSize : 0,
_anchorWidth : 0,
_labelWidth : 0,
_marginWidth : 0,
options : {
label : "To : ",
listUrl : "#addressbook",
descMessage : "{0} & {1} more..."
},
_create : function () {
var self = this,
$view = this.element,
role = $view.jqmData( "role" ),
option = this.options,
inputbox = $( document.createElement( "input" ) ),
labeltag = $( document.createElement( "label" ) ),
moreBlock = $( document.createElement( "a" ) );
$view.hide().empty().addClass( "ui-" + role );
// create a label tag.
$( labeltag ).text( this.options.label ).addClass( "ui-multibuttonentry-label" );
$view.append( labeltag );
// create a input tag
$( inputbox ).text( option.label ).addClass( "ui-multibuttonentry-input" );
$view.append( inputbox );
// create a anchor tag.
$( moreBlock ).text( "+" ).attr( "href", option.listUrl ).addClass( "ui-multibuttonentry-link" );
// append default htmlelements to main widget.
$view.append( moreBlock );
// bind a event
this._bindEvents();
self._focusStatus = "init";
// display widget
$view.show();
$view.attr( "tabindex", -1 ).focusin( function ( e ) {
self.focusIn();
});
// assign global variables
self._viewWidth = $view.innerWidth();
self._reservedWidth += self._calcBlockWidth( moreBlock );
self._reservedWidth += self._calcBlockWidth( labeltag );
self._fontSize = parseInt( $( moreBlock ).css( "font-size" ), 10 );
self._currentWidth = self._reservedWidth;
},
// bind events
_bindEvents : function () {
var self = this,
$view = self.element,
option = self.options,
inputbox = $view.find( ".ui-multibuttonentry-input" ),
moreBlock = $view.find( ".ui-multibuttonentry-link" );
inputbox.bind( "keydown", function ( event ) {
// 8 : backspace
// 13 : Enter
var keyValue = event.keyCode,
valueString = $( inputbox ).val();
if ( keyValue == 8 ) {
if ( valueString.length === 0 ) {
self._validateTargetBlock();
}
} else if ( keyValue == 13 ) {
if ( valueString.length !== 0 ) {
self._addTextBlock( valueString );
}
inputbox.val( "" );
} else {
self._unlockTextBlock();
}
});
moreBlock.click( function () {
$.mobile.changePage( option.listUrl, {
transition: "slide",
reverse: false,
changeHash: false
} );
} );
$( document ).bind( "pagechange.mbe", function ( event ) {
if ( $view.innerWidth() === 0 ) {
return ;
}
var inputBox = $view.find( ".ui-multibuttonentry-input" );
if ( self._labelWidth === 0 ) {
self._labelWidth = $view.find( ".ui-multibuttonentry-label" ).outerWidth( true );
self._anchorWidth = $view.find( ".ui-multibuttonentry-link" ).outerWidth( true );
self._marginWidth = parseInt( ( $( inputBox ).css( "margin-left" ) ), 10 );
self._marginWidth += parseInt( ( $( inputBox ).css( "margin-right" ) ), 10 );
self._viewWidth = $view.innerWidth();
}
self._modifyInputBoxWidth();
});
},
// create a textbutton and append this button to parent layer.
// @param arg1 : string
// @param arg2 : index
_addTextBlock : function ( messages, blcokIndex ) {
if ( arguments.length === 0 ) {
return;
}
if ( ! messages ) {
return ;
}
var self = this,
$view = self.element,
content = messages,
index = blcokIndex,
blocks = null,
dataBlock = null,
displayText = null,
textBlock = null;
if ( self._viewWidth === 0 ) {
self._viewWidth = $view.innerWidth();
}
// save src data
dataBlock = $( document.createElement( 'input' ) );
dataBlock.val( content ).addClass( "ui-multibuttonentry-data" ).hide();
// Create a new text HTMLDivElement.
textBlock = $( document.createElement( 'div' ) );
displayText = self._ellipsisTextBlock( content ) ;
textBlock.text( displayText ).addClass( "ui-multibuttonentry-block" );
textBlock.append( dataBlock );
// bind a event to HTMLDivElement.
textBlock.bind( "vclick", function ( event ) {
if ( self._focusStatus === "focusOut" ) {
self.focusInEvent();
return;
}
if ( $( this ).hasClass( "ui-multibuttonentry-sblock" ) ) {
// If block is selected, it will be removed.
self._removeTextBlock();
}
var lockBlock = $view.find( "div.ui-multibuttonentry-sblock" );
if ( typeof lockBlock != "undefined" ) {
lockBlock.removeClass( "ui-multibuttonentry-sblock" ).addClass( "ui-multibuttonentry-block" );
}
$( this ).removeClass( "ui-multibuttonentry-block" ).addClass( "ui-multibuttonentry-sblock" );
self._trigger( "select" );
});
blocks = $view.find( "div" );
if ( index !== null && index <= blocks.length ) {
$( blocks[index] ).before( textBlock );
} else {
$view.find( ".ui-multibuttonentry-input" ).before( textBlock );
}
self._currentWidth += self._calcBlockWidth( textBlock );
self._modifyInputBoxWidth();
self._trigger( "add" );
},
_removeTextBlock : function () {
var self = this,
$view = this.element,
targetBlock = null,
lockBlock = $view.find( "div.ui-multibuttonentry-sblock" );
if ( lockBlock !== null && lockBlock.length > 0 ) {
self._currentWidth -= self._calcBlockWidth( lockBlock );
lockBlock.remove();
self._modifyInputBoxWidth();
this._trigger( "remove" );
} else {
$view.find( "div:last" ).removeClass( "ui-multibuttonentry-block" ).addClass( "ui-multibuttonentry-sblock" );
}
},
_calcBlockWidth : function ( block ) {
var blockWidth = 0;
blockWidth = $( block ).outerWidth( true );
return blockWidth;
},
_unlockTextBlock : function () {
var $view = this.element,
lockBlock = $view.find( "div.ui-multibuttonentry-sblock" );
if ( lockBlock !== null ) {
lockBlock.removeClass( "ui-multibuttonentry-sblock" ).addClass( "ui-multibuttonentry-block" );
}
},
// call when remove text block by backspace key.
_validateTargetBlock : function () {
var self = this,
$view = self.element,
lastBlock = $view.find( "div:last" ),
tmpBlock = null;
if ( lastBlock.hasClass( "ui-multibuttonentry-sblock" ) ) {
self._removeTextBlock();
} else {
tmpBlock = $view.find( "div.ui-multibuttonentry-sblock" );
tmpBlock.removeClass( "ui-multibuttonentry-sblock" ).addClass( "ui-multibuttonentry-block" );
lastBlock.removeClass( "ui-multibuttonentry-block" ).addClass( "ui-multibuttonentry-sblock" );
}
},
_ellipsisTextBlock : function ( text ) {
var self = this,
str = text,
length = 0,
maxWidth = self._viewWidth,
maxCharCnt = parseInt( ( self._viewWidth / self._fontSize ), 10 ) - 5,
ellipsisStr = null;
if ( str ) {
length = str.length ;
if ( length > maxCharCnt ) {
ellipsisStr = str.substring( 0, maxCharCnt );
ellipsisStr += "...";
} else {
ellipsisStr = str;
}
}
return ellipsisStr;
},
_modifyInputBoxWidth : function () {
var self = this,
$view = self.element,
labelWidth = self._labelWidth,
anchorWidth = self._anchorWidth,
inputBoxWidth = self._viewWidth - labelWidth - anchorWidth,
blocks = $view.find( "div" ),
blockWidth = 0,
index = 0,
margin = self._marginWidth,
inputBox = $view.find( ".ui-multibuttonentry-input" );
if ( $view.width() === 0 ) {
return ;
}
for ( index = 0; index < blocks.length; index += 1 ) {
blockWidth = self._calcBlockWidth( blocks[index] );
inputBoxWidth = inputBoxWidth - blockWidth;
if ( inputBoxWidth <= 0 ) {
if ( inputBoxWidth + anchorWidth >= 0 ) {
inputBoxWidth = self._viewWidth - anchorWidth;
} else {
inputBoxWidth = self._viewWidth - blockWidth - anchorWidth;
}
}
}
$( inputBox ).width( inputBoxWidth - margin - 1 );
},
_stringFormat : function ( expression ) {
var pattern = null,
message = expression,
i = 0;
for ( i = 1; i < arguments.length; i += 1 ) {
pattern = "{" + ( i - 1 ) + "}";
message = message.replace( pattern, arguments[i] );
}
return message;
},
_resizeBlock : function () {
var self = this,
$view = self.element,
dataBlocks = $( ".ui-multibuttonentry-data" ),
blocks = $view.find( "div" ),
srcTexts = [],
index = 0;
$view.hide();
for ( index = 0 ; index < dataBlocks.length ; index += 1 ) {
srcTexts[index] = $( dataBlocks[index] ).val();
self._addTextBlock( srcTexts[index] );
}
blocks.remove();
$view.show();
},
//----------------------------------------------------//
// Public Method //
//----------------------------------------------------//
//
// Focus In Event
//
focusIn : function () {
if ( this._focusStatus === "focusIn" ) {
return;
}
var $view = this.element;
$view.find( "label" ).show();
$view.find( ".ui-multibuttonentry-desclabel" ).remove();
$view.find( "div.ui-multibuttonentry-sblock" ).removeClass( "ui-multibuttonentry-sblock" ).addClass( "ui-multibuttonentry-block" );
$view.find( "div" ).show();
$view.find( ".ui-multibuttonentry-input" ).show();
$view.find( "a" ).show();
// change focus state.
this._modifyInputBoxWidth();
this._focusStatus = "focusIn";
},
focusOut : function () {
if ( this._focusStatus === "focusOut" ) {
return;
}
var self = this,
$view = self.element,
tempBlock = null,
statement = "",
index = 0,
lastIndex = 10,
label = $view.find( "label" ),
more = $view.find( "span" ),
blocks = $view.find( "div" ),
currentWidth = $view.outerWidth( true ) - more.outerWidth( true ) - label.outerWidth( true ),
textWidth = currentWidth;
$view.find( ".ui-multibuttonentry-input" ).hide();
$view.find( "a" ).hide();
blocks.hide();
// div button
currentWidth = currentWidth - self._reservedWidth;
for ( index = 0; index < blocks.length; index += 1 ) {
currentWidth = currentWidth - $( blocks[index] ).outerWidth( true );
statement += ", " + $( blocks[index] ).text();
if ( currentWidth <= 0 ) {
statement = "," + $( blocks[0] ).text();
statement = self._stringFormat( self.options.descMessage, statement, blocks.length - 1 );
break;
}
lastIndex = statement.length;
}
tempBlock = $( document.createElement( 'input' ) );
tempBlock.val( statement.substr( 1, statement.length ) );
tempBlock.addClass( "ui-multibuttonentry-desclabel" ).addClass( "ui-multibuttonentry-desclabel" );
tempBlock.width( textWidth - ( self._reservedWidth ) );
tempBlock.attr( "disabled", true );
$view.find( "label" ).after( tempBlock );
// update foucs state
this._focusStatus = "focusOut";
},
inputText : function ( message ) {
var $view = this.element;
if ( arguments.length === 0 ) {
return $view.find( ".ui-multibuttonentry-input" ).val();
}
$view.find( ".ui-multibuttonentry-input" ).val( message );
return message;
},
select : function ( index ) {
var $view = this.element,
lockBlock = null,
blocks = null;
if ( this._focusStatus === "focusOut" ) {
return;
}
if ( arguments.length === 0 ) {
// return a selected block.
lockBlock = $view.find( "div.ui-multibuttonentry-sblock" );
if ( lockBlock) {
return lockBlock.text();
}
return null;
}
// 1. unlock all blocks.
this._unlockTextBlock();
// 2. select pointed block.
blocks = $view.find( "div" );
if ( blocks.length > index ) {
$( blocks[index] ).removeClass( "ui-multibuttonentry-block" ).addClass( "ui-multibuttonentry-sblock" );
this._trigger( "select" );
}
return null;
},
add : function ( message, position ) {
if ( this._focusStatus === "focusOut" ) {
return;
}
this._addTextBlock( message, position );
},
remove : function ( position ) {
var self = this,
$view = this.element,
blocks = $view.find( "div" ),
index = 0;
if ( this._focusStatus === "focusOut" ) {
return;
}
if ( arguments.length === 0 ) {
blocks.remove();
this._trigger( "clear" );
} else if ( typeof position == "number" ) {
// remove selected button
index = ( ( position < blocks.length ) ? position : ( blocks.length - 1 ) );
$( blocks[index] ).remove();
this._trigger( "remove" );
}
self._modifyInputBoxWidth();
},
length : function () {
return this.element.find( "div" ).length;
},
refresh : function () {
var self = this;
self.element.hide();
self.element.show();
},
destory : function () {
var $view = this.element;
$view.find( "label" ).remove();
$view.find( "div" ).unbind( "vclick" ).remove();
$view.find( "a" ).remove();
$view.find( ".ui-multibuttonentry-input" ).unbind( "keydown" ).remove();
this._trigger( "destory" );
}
});
$( document ).bind( "pagecreate create", function () {
$( ":jqmData(role='multibuttonentry')" ).multibuttonentry();
});
$( window ).bind( "resize", function () {
$( ":jqmData(role='multibuttonentry')" ).multibuttonentry( "refresh" );
});
} ( jQuery, window, document ) );
/*
* Authors: Yonghwi Park <yonghwi0324.park@samsung.com>
* Wonseop Kim <wonseop.kim@samsung.com>
*/
/**
* MultiMediaView is a widget that provides an audio or a video content handling features.
* A multi-media content handled with this widget can be played with HTML5's <audio> or <video> tag.
* If a user wants to play a music file, he should use "<audio>" tag.
* And he should use "<video>" tag to play a video file.
*
* HTML Attributes:
* data-theme : Set a theme of widget.
* If this value is not defined, widget will use parent`s theme. (optional)
* data-controls : If this value is 'true', widget will use belonging controller.
* If this value is 'false', widget will use browser`s controller.
* Default value is 'true'.
* data-fullscreen : Set a status that fullscreen when inital start.
* Default value is 'false'.
*
* APIs:
* width( [number] )
* : Get or set a widget of widget.
* height( [number] )
* : Get or set a height of widget.
* size( number, number )
* : Set a size of widget and resize a widget.
* First argument is width and second argument is height.
* fullscreen( [boolean] )
* : Set a status that fullscreen.
*
* Events:
*
* create : triggered when a multimediaview is created.
*
* Examples:
*
* VIDEO :
* <video data-controls="true" style="width:100%;">
* <source src="media/oceans-clip.mp4" type="video/mp4" />
* Your browser does not support the video tag.
* </video>
*
* AUDIO :
* <audio data-controls="true" style="width:100%;">
* <source src="media/Over the horizon.mp3" type="audio/mp3" />
* Your browser does not support the audio tag.
* </audio>
*
*/
( function ( $, document, window, undefined ) {
$.widget( "tizen.multimediaview", $.mobile.widget, {
options : {
theme : null,
controls : true,
fullscreen : false,
initSelector : "video, audio"
},
_create : function () {
var self = this,
view = self.element,
viewElement = view[0],
option = self.options,
role = "multimediaview",
control = null;
$.extend( this, {
role : null,
isControlHide : false,
controlTimer : null,
isVolumeHide : true,
isVertical : true,
backupView : null
});
self.role = role;
view.addClass( "ui-multimediaview" );
control = self._createControl();
if ( view[0].nodeName === "AUDIO" ) {
control.addClass( "ui-multimediaview-audio" );
}
control.hide();
view.wrap( "<div class='ui-multimediaview-wrap'>" ).after( control );
if ( option.controls ) {
if ( view.attr("controls") ) {
view.removeAttr( "controls" );
}
}
self._addEvent();
$( document ).bind( "pagechange.multimediaview", function ( e ) {
var $page = $( e.target );
if ( $page.find( view ).length > 0 && viewElement.autoplay ) {
viewElement.play();
}
if ( option.controls ) {
control.show();
self._resize();
}
}).bind( "pagebeforechange.multimediaview", function ( e ) {
if ( viewElement.played.length !== 0 ) {
viewElement.pause();
control.hide();
}
});
$( window ).bind( "resize.multimediaview orientationchange.multimediaview", function ( e ) {
if ( !option.controls ) {
return;
}
var $page = $( e.target ),
$scrollview = view.parents( ".ui-scrollview-clip" );
$scrollview.each( function ( i ) {
if ( $.data( this, "scrollview" ) ) {
$( this ).scrollview( "scrollTo", 0, 0 );
}
});
// for maintaining page layout
if ( !option.fullscreen ) {
$( ".ui-footer:visible" ).show();
} else {
$( ".ui-footer" ).hide();
self._fitContentArea( $page );
}
self._resize();
});
},
_resize : function () {
var view = this.element,
parent = view.parent(),
control = parent.find( ".ui-multimediaview-control" ),
viewWidth = 0,
viewHeight = 0,
viewOffset = null;
this._resizeFullscreen( this.options.fullscreen );
viewWidth = ( ( view[0].nodeName === "VIDEO" ) ? view.width() : parent.width() );
viewHeight = ( ( view[0].nodeName === "VIDEO" ) ? view.height() : control.height() );
viewOffset = view.offset();
this._resizeControl( viewOffset, viewWidth, viewHeight );
this._updateSeekBar();
this._updateVolumeState();
},
_resizeControl : function ( offset, width, height ) {
var self = this,
view = self.element,
viewElement = view[0],
control = view.parent().find( ".ui-multimediaview-control" ),
buttons = control.find( ".ui-button" ),
playpauseButton = control.find( ".ui-playpausebutton" ),
volumeControl = control.find( ".ui-volumecontrol" ),
seekBar = control.find( ".ui-seekbar" ),
durationLabel = control.find( ".ui-durationlabel" ),
controlWidth = width,
controlHeight = control.outerHeight( true ),
availableWidth = 0,
controlOffset = null;
if ( control ) {
if ( view[0].nodeName === "VIDEO" ) {
controlOffset = control.offset();
controlOffset.left = offset.left;
controlOffset.top = offset.top + height - controlHeight;
control.offset( controlOffset );
}
control.width( controlWidth );
}
if ( seekBar ) {
availableWidth = control.width() - ( buttons.outerWidth( true ) * buttons.length );
availableWidth -= ( parseInt( buttons.eq( 0 ).css( "margin-left" ), 10 ) + parseInt( buttons.eq( 0 ).css( "margin-right" ), 10 ) ) * buttons.length;
if ( !self.isVolumeHide ) {
availableWidth -= volumeControl.outerWidth( true );
}
seekBar.width( availableWidth );
}
if ( durationLabel && !isNaN( viewElement.duration ) ) {
durationLabel.find( "p" ).text( self._convertTimeFormat( viewElement.duration ) );
}
if ( viewElement.autoplay && viewElement.paused === false ) {
playpauseButton.removeClass( "ui-play-icon" ).addClass( "ui-pause-icon" );
}
},
_resizeFullscreen : function ( isFullscreen ) {
var self = this,
view = self.element,
parent = view.parent(),
control = view.parent().find( ".ui-multimediaview-control" ),
playpauseButton = control.find( ".ui-playpausebutton" ),
timestampLabel = control.find( ".ui-timestamplabel" ),
seekBar = control.find( ".ui-seekbar" ),
durationBar = seekBar.find( ".ui-duration" ),
currenttimeBar = seekBar.find( ".ui-currenttime" ),
docWidth = 0,
docHeight = 0;
if ( isFullscreen ) {
if ( !self.backupView ) {
self.backupView = {
width : view[0].style.getPropertyValue( "width" ) || "",
height : view[0].style.getPropertyValue( "height" ) || "",
position : view.css( "position" ),
zindex : view.css( "z-index" )
};
}
docWidth = $( "body" )[0].clientWidth;
docHeight = $( "body" )[0].clientHeight;
view.width( docWidth ).height( docHeight - 1 );
view.addClass( "ui-" + self.role + "-fullscreen" );
view.offset( {
top : 0,
left : 0
});
} else {
if ( !self.backupView ) {
return;
}
view.removeClass( "ui-" + self.role + "-fullscreen" );
view.css( {
"width" : self.backupView.width,
"height" : self.backupView.height,
"position": self.backupView.position,
"z-index": self.backupView.zindex
});
self.backupView = null;
}
parent.show();
},
_addEvent : function () {
var self = this,
view = self.element,
viewElement = view[0],
control = view.parent().find( ".ui-multimediaview-control" ),
playpauseButton = control.find( ".ui-playpausebutton" ),
timestampLabel = control.find( ".ui-timestamplabel" ),
durationLabel = control.find( ".ui-durationlabel" ),
volumeButton = control.find( ".ui-volumebutton" ),
volumeControl = control.find( ".ui-volumecontrol" ),
volumeBar = volumeControl.find( ".ui-volumebar" ),
volumeGuide = volumeControl.find( ".ui-guide" ),
volumeHandle = volumeControl.find( ".ui-handler" ),
fullscreenButton = control.find( ".ui-fullscreenbutton" ),
seekBar = control.find( ".ui-seekbar" ),
durationBar = seekBar.find( ".ui-duration" ),
currenttimeBar = seekBar.find( ".ui-currenttime" );
view.bind( "loadedmetadata.multimediaview", function ( e ) {
if ( !isNaN( viewElement.duration ) ) {
durationLabel.find( "p" ).text( self._convertTimeFormat( viewElement.duration ) );
}
self._resize();
}).bind( "timeupdate.multimediaview", function ( e ) {
self._updateSeekBar();
}).bind( "play.multimediaview", function ( e ) {
playpauseButton.removeClass( "ui-play-icon" ).addClass( "ui-pause-icon" );
}).bind( "pause.multimediaview", function ( e ) {
playpauseButton.removeClass( "ui-pause-icon" ).addClass( "ui-play-icon" );
}).bind( "ended.multimediaview", function ( e ) {
if ( typeof viewElement.loop == "undefined" || viewElement.loop === "" ) {
self.stop();
}
}).bind( "volumechange.multimediaview", function ( e ) {
if ( viewElement.volume < 0.1 ) {
viewElement.muted = true;
volumeButton.removeClass( "ui-volume-icon" ).addClass( "ui-mute-icon" );
} else {
viewElement.muted = false;
volumeButton.removeClass( "ui-mute-icon" ).addClass( "ui-volume-icon" );
}
if ( !self.isVolumeHide ) {
self._updateVolumeState();
}
}).bind( "durationchange.multimediaview", function ( e ) {
if ( !isNaN( viewElement.duration ) ) {
durationLabel.find( "p" ).text( self._convertTimeFormat( viewElement.duration ) );
}
self._resize();
}).bind( "error.multimediaview", function ( e ) {
switch ( e.target.error.code ) {
case e.target.error.MEDIA_ERR_ABORTED :
window.alert( 'You aborted the video playback.' );
break;
case e.target.error.MEDIA_ERR_NETWORK :
window.alert( 'A network error caused the video download to fail part-way.' );
break;
case e.target.error.MEDIA_ERR_DECODE :
window.alert( 'The video playback was aborted due to a corruption problem or because the video used features your browser did not support.' );
break;
case e.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED :
window.alert( 'The video could not be loaded, either because the server or network failed or because the format is not supported.' );
break;
default :
window.alert( 'An unknown error occurred.' );
break;
}
}).bind( "vclick.multimediaview", function ( e ) {
if ( !self.options.controls ) {
return;
}
control.fadeToggle( "fast", function () {
var offset = control.offset();
self.isControlHide = !self.isControlHide;
if ( self.options.mediatype == "video" ) {
self._startTimer();
}
});
self._resize();
});
playpauseButton.bind( "vclick.multimediaview", function () {
self._endTimer();
if ( viewElement.paused ) {
viewElement.play();
} else {
viewElement.pause();
}
if ( self.options.mediatype == "video" ) {
self._startTimer();
}
});
fullscreenButton.bind( "vclick.multimediaview", function () {
self.fullscreen( !self.options.fullscreen );
control.fadeIn( "fast" );
self._endTimer();
});
seekBar.bind( "vmousedown.multimediaview", function ( e ) {
var x = e.clientX,
duration = viewElement.duration,
durationOffset = durationBar.offset(),
durationWidth = durationBar.width(),
timerate = ( x - durationOffset.left ) / durationWidth,
time = duration * timerate;
viewElement.currentTime = time;
self._endTimer();
e.preventDefault();
e.stopPropagation();
$( document ).bind( "vmousemove.multimediaview", function ( e ) {
var x = e.clientX,
timerate = ( x - durationOffset.left ) / durationWidth;
viewElement.currentTime = duration * timerate;
e.preventDefault();
e.stopPropagation();
}).bind( "vmouseup.multimediaview", function () {
$( document ).unbind( "vmousemove.multimediaview vmouseup.multimediaview" );
if ( viewElement.paused ) {
viewElement.pause();
} else {
viewElement.play();
}
});
});
volumeButton.bind( "vclick.multimediaview", function () {
if ( self.isVolumeHide ) {
var view = self.element,
volume = viewElement.volume;
self.isVolumeHide = false;
self._resize();
volumeControl.fadeIn( "fast" );
self._updateVolumeState();
self._updateSeekBar();
} else {
self.isVolumeHide = true;
volumeControl.fadeOut( "fast", function () {
self._resize();
});
self._updateSeekBar();
}
});
volumeBar.bind( "vmousedown.multimediaview", function ( e ) {
var baseX = e.clientX,
volumeGuideLeft = volumeGuide.offset().left,
volumeGuideWidth = volumeGuide.width(),
volumeBase = volumeGuideLeft + volumeGuideWidth,
handlerOffset = volumeHandle.offset(),
volumerate = ( baseX - volumeGuideLeft ) / volumeGuideWidth,
currentVolume = ( baseX - volumeGuideLeft ) / volumeGuideWidth;
self._endTimer();
self._setVolume( currentVolume.toFixed( 2 ) );
e.preventDefault();
e.stopPropagation();
$( document ).bind( "vmousemove.multimediaview", function ( e ) {
var currentX = e.clientX,
currentVolume = ( currentX - volumeGuideLeft ) / volumeGuideWidth;
self._setVolume( currentVolume.toFixed( 2 ) );
e.preventDefault();
e.stopPropagation();
}).bind( "vmouseup.multimediaview", function () {
$( document ).unbind( "vmousemove.multimediaview vmouseup.multimediaview" );
if ( self.options.mediatype == "video" ) {
self._startTimer();
}
});
});
},
_removeEvent : function () {
var self = this,
view = self.element,
control = view.parent().find( ".ui-multimediaview-control" ),
playpauseButton = control.find( ".ui-playpausebutton" ),
fullscreenButton = control.find( ".ui-fullscreenbutton" ),
seekBar = control.find( ".ui-seekbar" ),
volumeControl = control.find( ".ui-volumecontrol" ),
volumeBar = volumeControl.find( ".ui-volumebar" ),
volumeHandle = volumeControl.find( ".ui-handler" );
view.unbind( ".multimediaview" );
playpauseButton.unbind( ".multimediaview" );
fullscreenButton.unbind( ".multimediaview" );
seekBar.unbind( ".multimediaview" );
volumeBar.unbind( ".multimediaview" );
volumeHandle.unbind( ".multimediaview" );
},
_createControl : function () {
var self = this,
view = self.element,
control = $( "<span></span>" ),
playpauseButton = $( "<span></span>" ),
seekBar = $( "<span></span>" ),
timestampLabel = $( "<span><p>00:00:00</p></span>" ),
durationLabel = $( "<span><p>00:00:00</p></span>" ),
volumeButton = $( "<span></span>" ),
volumeControl = $( "<span></span>" ),
volumeBar = $( "<div></div>" ),
volumeGuide = $( "<span></span>" ),
volumeValue = $( "<span></span>" ),
volumeHandle = $( "<span></span>" ),
fullscreenButton = $( "<span></span>" ),
durationBar = $( "<span></span>" ),
currenttimeBar = $( "<span></span>" );
control.addClass( "ui-" + self.role + "-control" );
playpauseButton.addClass( "ui-playpausebutton ui-button" );
seekBar.addClass( "ui-seekbar" );
timestampLabel.addClass( "ui-timestamplabel" );
durationLabel.addClass( "ui-durationlabel" );
volumeButton.addClass( "ui-volumebutton ui-button" );
fullscreenButton.addClass( "ui-fullscreenbutton ui-button" );
durationBar.addClass( "ui-duration" );
currenttimeBar.addClass( "ui-currenttime" );
volumeControl.addClass( "ui-volumecontrol" );
volumeBar.addClass( "ui-volumebar" );
volumeGuide.addClass( "ui-guide" );
volumeValue.addClass( "ui-value" );
volumeHandle.addClass( "ui-handler" );
seekBar.append( durationBar ).append( currenttimeBar ).append( durationLabel ).append( timestampLabel );
playpauseButton.addClass( "ui-play-icon" );
if ( view[0].muted ) {
$( volumeButton ).addClass( "ui-mute-icon" );
} else {
$( volumeButton ).addClass( "ui-volume-icon" );
}
volumeBar.append( volumeGuide ).append( volumeValue ).append( volumeHandle );
volumeControl.append( volumeBar );
control.append( playpauseButton ).append( seekBar ).append( volumeControl ).append( volumeButton );
if ( self.element[0].nodeName === "VIDEO" ) {
$( fullscreenButton ).addClass( "ui-fullscreen-on" );
control.append( fullscreenButton );
}
volumeControl.hide();
return control;
},
_startTimer : function ( duration ) {
this._endTimer();
if ( !duration ) {
duration = 3000;
}
var self = this,
view = self.element,
control = view.parent().find( ".ui-multimediaview-control" ),
volumeControl = control.find( ".ui-volumecontrol" );
self.controlTimer = setTimeout( function () {
self.isVolumeHide = true;
self.isControlHide = true;
self.controlTimer = null;
volumeControl.hide();
control.fadeOut( "fast" );
}, duration );
},
_endTimer : function () {
if ( this.controlTimer ) {
clearTimeout( this.controlTimer );
this.controlTimer = null;
}
},
_convertTimeFormat : function ( systime ) {
var ss = parseInt( systime % 60, 10 ).toString(),
mm = parseInt( ( systime / 60 ) % 60, 10 ).toString(),
hh = parseInt( systime / 3600, 10 ).toString(),
time = ( ( hh.length < 2 ) ? "0" + hh : hh ) + ":" +
( ( mm.length < 2 ) ? "0" + mm : mm ) + ":" +
( ( ss.length < 2 ) ? "0" + ss : ss );
return time;
},
_updateSeekBar : function ( currenttime ) {
var self = this,
view = self.element,
duration = view[0].duration,
control = view.parent().find( ".ui-multimediaview-control" ),
seekBar = control.find( ".ui-seekbar" ),
durationBar = seekBar.find( ".ui-duration" ),
currenttimeBar = seekBar.find( ".ui-currenttime" ),
timestampLabel = control.find( ".ui-timestamplabel" ),
durationOffset = durationBar.offset(),
durationWidth = durationBar.width(),
durationHeight = durationBar.height(),
timebarWidth = 0;
if ( typeof currenttime == "undefined" ) {
currenttime = view[0].currentTime;
}
timebarWidth = parseInt( currenttime / duration * durationWidth, 10 );
durationBar.offset( durationOffset );
currenttimeBar.offset( durationOffset ).width( timebarWidth );
timestampLabel.find( "p" ).text( self._convertTimeFormat( currenttime ) );
},
_updateVolumeState : function () {
var self = this,
view = self.element,
control = view.parent().find( ".ui-multimediaview-control" ),
volumeControl = control.find( ".ui-volumecontrol" ),
volumeButton = control.find( ".ui-volumebutton" ),
volumeBar = volumeControl.find( ".ui-volumebar" ),
volumeGuide = volumeControl.find( ".ui-guide" ),
volumeValue = volumeControl.find( ".ui-value" ),
volumeHandle = volumeControl.find( ".ui-handler" ),
handlerWidth = volumeHandle.width(),
handlerHeight = volumeHandle.height(),
volumeGuideHeight = volumeGuide.height(),
volumeGuideWidth = volumeGuide.width(),
volumeGuideTop = 0,
volumeGuideLeft = 0,
volumeBase = 0,
handlerOffset = null,
volume = view[0].volume;
volumeGuideTop = parseInt( volumeGuide.offset().top, 10 );
volumeGuideLeft = parseInt( volumeGuide.offset().left, 10 );
volumeBase = volumeGuideLeft;
handlerOffset = volumeHandle.offset();
handlerOffset.top = volumeGuideTop - parseInt( ( handlerHeight - volumeGuideHeight ) / 2, 10 );
handlerOffset.left = volumeBase + parseInt( volumeGuideWidth * volume, 10 ) - parseInt( handlerWidth / 2, 10 );
volumeHandle.offset( handlerOffset );
volumeValue.width( parseInt( volumeGuideWidth * ( volume ), 10 ) );
},
_setVolume : function ( value ) {
var viewElement = this.element[0];
if ( value < 0.0 || value > 1.0 ) {
return;
}
viewElement.volume = value;
},
_fitContentArea: function ( page, parent ) {
if ( typeof parent == "undefined" ) {
parent = window;
}
var $page = $( page ),
$content = $( ".ui-content:visible:first" ),
hh = $( ".ui-header:visible" ).outerHeight() || 0,
fh = $( ".ui-footer:visible" ).outerHeight() || 0,
pt = parseFloat( $content.css( "padding-top" ) ),
pb = parseFloat( $content.css( "padding-bottom" ) ),
wh = ( ( parent === window ) ? window.innerHeight : $( parent ).height() ),
height = wh - ( hh + fh ) - ( pt + pb );
$content.offset( {
top : ( hh + pt )
}).height( height );
},
width : function ( value ) {
var self = this,
args = arguments,
view = self.element;
if ( args.length === 0 ) {
return view.width();
}
if ( args.length === 1 ) {
view.width( value );
self._resize();
}
},
height : function ( value ) {
var self = this,
view = self.element,
args = arguments;
if ( args.length === 0 ) {
return view.height();
}
if ( args.length === 1 ) {
view.height( value );
self._resize();
}
},
size : function ( width, height ) {
var self = this,
view = self.element;
view.width( width ).height( height );
self._resize();
},
fullscreen : function ( value ) {
var self = this,
view = self.element,
control = view.parent().find( ".ui-multimediaview-control" ),
fullscreenButton = control.find( ".ui-fullscreenbutton" ),
args = arguments,
option = self.options,
currentPage = $( ".ui-page-active" );
if ( args.length === 0 ) {
return option.fullscreen;
}
if ( args.length === 1 ) {
view.parents( ".ui-content" ).scrollview( "scrollTo", 0, 0 );
this.options.fullscreen = value;
if ( value ) {
currentPage.children( ".ui-header" ).hide();
currentPage.children( ".ui-footer" ).hide();
this._fitContentArea( currentPage );
fullscreenButton.removeClass( "ui-fullscreen-on" ).addClass( "ui-fullscreen-off" );
} else {
currentPage.children( ".ui-header" ).show();
currentPage.children( ".ui-footer" ).show();
this._fitContentArea( currentPage );
fullscreenButton.removeClass( "ui-fullscreen-off" ).addClass( "ui-fullscreen-on" );
}
self._resize();
}
},
refresh : function () {
this._resize();
}
});
$( document ).bind( "pagecreate create", function ( e ) {
$.tizen.multimediaview.prototype.enhanceWithin( e.target );
});
} ( jQuery, document, window ) );
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Author: Minkyu Kang <mk7.kang@samsung.com>
*/
/*
* nocontents widget
*
* HTML Attributes
*
* data-role: set to 'nocontents'.
* data-text1: top message.
* data-text2: bottom message.
* data-type: type of nocontents. You can set text, picture, multimedia and unnamed.
*
* APIs
*
* N/A
*
* Events
*
* N/A
*
* Examples
*
* Text Type
* <div data-role="nocontents" id="nocontents" data-text1="Text1" data-text2="Text2" data-type="text"></div>
*
* Picture Type
* <div data-role="nocontents" id="nocontents" data-text1="Text1" data-text2="Text2" data-type="picture"></div>
*
* Multimedia Type
* <div data-role="nocontents" id="nocontents" data-text1="Text1" data-text2="Text2" data-type="multimedia"></div>
*
* Unnamed Type
* <div data-role="nocontents" id="nocontents" data-text1="Text1" data-text2="Text2"></div>
* or
* <div data-role="nocontents" id="nocontents" data-text1="Text1" data-text2="Text2" data-type="unnamed"></div>
*
*/
(function ( $, window, undefined ) {
$.widget( "tizen.nocontents", $.mobile.widget, {
max_height: 0,
container: null,
icon_img: null,
text0_bg: null,
text1_bg: null,
_get_height: function () {
var $page = $('.ui-page'),
$content = $page.children('.ui-content'),
$header = $page.children('.ui-header'),
$footer = $page.children('.ui-footer'),
header_h = $header.outerHeight() || 0,
footer_h = $footer.outerHeight() || 0,
padding_t = parseFloat( $content.css('padding-top') ) || 0,
padding_b = parseFloat( $content.css('padding-bottom') ) || 0,
content_h = $(window).height() - header_h - footer_h -
(padding_t + padding_b) * 2,
container_h = this.container.height();
return ( content_h < container_h ? container_h : content_h );
},
_align: function () {
var content_height = this._get_height(),
icon_height = this.icon_img.height(),
icon_width = this.icon_img.width(),
content_gap = 46,
text0_height = this.text0_bg.height() || 0,
text1_height = this.text1_bg.height() || 0,
text_top = 0,
icon_top = (content_height -
(icon_height + content_gap +
text0_height + text1_height)) / 2;
if ( icon_top < content_gap ) {
icon_top = content_gap;
}
this.container.height( content_height );
this.icon_img.css( 'left',
($(window).width() - icon_width) / 2 );
this.icon_img.css( 'top', icon_top );
text_top = icon_top + icon_height + content_gap;
this.text0_bg.css( 'top', text_top );
this.text1_bg.css( 'top', text_top + text0_height );
},
_create: function () {
var icon_type = $( this.element ).jqmData('type'),
text = new Array(2);
if ( icon_type === undefined ||
(icon_type !== "picture" &&
icon_type !== "multimedia" &&
icon_type !== "text") ) {
icon_type = "unnamed";
}
text[0] = $( this.element ).jqmData('text1');
text[1] = $( this.element ).jqmData('text2');
if ( text[0] === undefined ) {
text[0] = "";
}
if ( text[1] === undefined ) {
text[1] = "";
}
this.container = $('<div class="ui-nocontents"/>');
this.icon_img = $('<div class="ui-nocontents-icon-' +
icon_type + '"/>');
this.text0_bg = $('<div class="ui-nocontents-text">' +
text[0] + '<div>');
this.text1_bg = $('<div class="ui-nocontents-text">' +
text[1] + '<div>');
this.container.append( this.icon_img );
this.container.append( this.text0_bg );
this.container.append( this.text1_bg );
$( this.element ).append( this.container );
this._align();
}
});
$( document ).bind( "pagecreate create", function ( e ) {
$( e.target ).find(":jqmData(role='nocontents')").nocontents();
});
} ( jQuery, this ));
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Author: Minkyu Kang <mk7.kang@samsung.com>
*/
/*
* Notification widget
*
* HTML Attributes
*
* data-role: set to 'notification'.
* data-type: 'ticker' or 'popup'.
* data-text1: top text for tickernoti, text to show for smallpopup.
* data-text2: bottom text for tickernoti, smallpopup will ignore this text.
* data-param: parameter for 'tapped' event.
* data-interval: time to showing. If don't set, will show infinitely.
*
* APIs
*
* show(): show the notification.
* hide(): hide the notification.
*
* Events
*
* tapped: When you tap or click the smallpopup, this event will be raised.
*
* Examples
*
* // tickernoti
* <div data-role="notification" id="notification" data-type="ticker" data-text1="text1" data-text2="text2" data-param="parameters" data-interval="3000"></div>
*
* // smallpopup
* <div data-role="notification" id="notification" data-type="popup" data-text1="text1" data-param="parameters" data-interval="3000"></div>
*
* // event
* $('#notification-demo').bind('tapped', function (e, m) {
* alert('notification is tapped\nparameter:"' + m + '"');
* });
*
*/
(function ( $, window ) {
$.widget( "tizen.notification", $.mobile.widget, {
btn: null,
param: null,
interval: null,
seconds: null,
running: false,
_refresh: function () {
this._del_event();
this._update();
this._add_event();
$( this.html ).addClass("fix");
},
show: function () {
if ( this.running ) {
this._refresh();
return;
}
this._update();
this._add_event();
this.running = true;
$( this.html ).addClass("show");
},
hide: function () {
if ( !this.running ) {
return;
}
$( this.html ).addClass("hide");
$( this.html ).removeClass("show").removeClass("fix");
this._del_event();
this.running = false;
},
close: function () {
$( this.html ).removeClass("show").removeClass("hide").removeClass("fix");
this._del_event();
this.running = false;
},
_get_container: function () {
if ( this.type === 'ticker' ) {
return $( this.element ).find(".ui-ticker");
}
return $( this.element ).find(".ui-smallpopup");
},
_add_event: function () {
var self = this,
container = this._get_container();
if ( this.type === 'ticker' ) {
container.find(".ui-ticker-btn").append( this.btn );
this.btn.bind( "vmouseup", function () {
self.hide();
});
}
container.bind( 'vmouseup', function () {
self.element.trigger( 'tapped', self.param );
self.hide();
});
if ( this.seconds !== undefined && this.second !== 0 ) {
this.interval = setInterval( function () {
self.hide();
}, this.seconds );
}
},
_del_event: function () {
var container = this._get_container();
if ( this.type === 'ticker' ) {
this.btn.unbind("vmouseup");
}
container.unbind('vmouseup');
clearInterval( this.interval );
},
_set_position: function () {
var container = this._get_container(),
container_h = parseFloat( container.css('height') ),
$page = $('.ui-page'),
$footer = $page.children('.ui-footer'),
footer_h = $footer.outerHeight() || 0,
position = $(window).height() - container_h - footer_h;
container.css( 'top', position );
},
_update: function () {
var text = new Array(2);
if ( this.html ) {
this.html.detach();
}
text[0] = $(this.element).jqmData('text1');
text[1] = $(this.element).jqmData('text2');
this.param = $(this.element).jqmData('param');
this.seconds = $(this.element).jqmData('interval');
this.type = $(this.element).jqmData('type') || 'popup';
if ( this.type === 'ticker' ) {
this.html = $('<div class="ui-ticker">' +
'<div class="ui-ticker-icon"></div>' +
'<div class="ui-ticker-text1-bg">' +
text[0] + '</div>' +
'<div class="ui-ticker-text2-bg">' +
text[1] + '</div>' +
'<div class="ui-ticker-body"></div>' +
'<div class="ui-ticker-btn"></div>' +
'</div>');
$( this.element ).append( this.html );
} else {
this.html = $('<div class="ui-smallpopup">' +
'<div class="ui-smallpopup-text-bg">' +
text[0] + '</div>' +
'</div>');
$( this.element ).append( this.html );
this._set_position();
}
},
_create: function () {
this.btn = $("<a href='#' class='ui-input-cancel' title='close' data-theme='s'>Close</a>")
.tap( function ( event ) {
event.preventDefault();
})
.buttonMarkup({
inline: true,
corners: true,
shadow: true
});
this._update();
this.running = false;
}
}); // End of widget
// auto self-init widgets
$( document ).bind( "pagecreate create", function ( e ) {
$( e.target ).find(":jqmData(role='notification')").notification();
});
$( document ).bind( "pagebeforehide", function ( e ) {
$( e.target ).find(":jqmData(role='notification')").notification('close');
});
}( jQuery, this ));
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
* Copyright (c) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Elliot Smith <elliot.smith@intel.com>
*/
// optionheader provides a collapsible toolbar for buttons and
// segmented controls directly under the title bar. It
// wraps a jQuery Mobile grid in a collapsible container; clicking
// on the container, or on one of the buttons inside the container,
// will collapse it.
//
// To add an option header to a page, mark up the header with a
// data-role="optionheader" attribute, as shown in this example:
//
// <div data-role="header">
// <h1>Option header - 3 buttons example</h1>
// <div data-role="optionheader">
// <div class="ui-grid-b">
// <div class="ui-block-a"><a data-role="button">Previous</a></div>
// <div class="ui-block-b"><a data-role="button">Cancel</a></div>
// <div class="ui-block-c"><a data-role="button">Next</a></div>
// </div>
// </div>
// </div>
//
// The optionheader can also be used inline (e.g. in a content block or
// a widget).
//
// Alternatively, use $('...').optionheader() to apply programmatically.
//
// The grid inside the optionheader should be marked up as for
// a standard jQuery Mobile grid. (The widget has been tested with one
// or two rows of 2-4 columns each.)
//
// Note that if you use this with fixed headers, you may find that
// expanding the option header increases the page size so that scrollbars
// appear (jQuery Mobile's own collapsible content areas cause the
// same issue). You can alleviate this somewhat by calling the show() method
// on the page toolbars each time the size of the header changes.
//
// The widget is configurable via a data-options attribute on the same
// div as the data-role="optionheader" attribute, e.g.
//
// <div data-role="header">
// <h1>Option header - configured</h1>
// <div data-role="optionheader" data-options='{"collapsed":true, "duration":1.5}'>
// <div class="ui-grid-b">
// <div class="ui-block-a"><a data-role="button">Previous</a></div>
// <div class="ui-block-b"><a data-role="button">Cancel</a></div>
// <div class="ui-block-c"><a data-role="button">Next</a></div>
// </div>
// </div>
// </div>
//
// Options can also be set with $(...).optionheader('option', 'name', value).
// However, if you do this, you'll need to call $(...).optionheader('refresh')
// afterwards for the new values to take effect (note that optionheader()
// can be applied multiple times to an element without side effects).
//
// See below for the available options.
//
// Theme: by default, gets a 'b' swatch; override with data-theme="X"
// as per usual
//
// Options (can be set with a data-options attribute):
//
// {Boolean} [showIndicator=true] Set to true (the default) to show
// the upward-pointing arrow indicator on top of the title bar.
// {Boolean} [startCollapsed=false] Sets the appearance when the option
// header is first displayed; defaults to false (i.e. show the header
// expanded on first draw). NB setting this option later has no
// effect: use collapse() to collapse a widget which is already
// drawn.
// {Boolean} [expandable=true] Sets whether the header will expand
// in response to clicks; default = true.
// {Float} [duration=0.25] Duration of the expand/collapse animation.
//
// Methods (see below for docs):
//
// toggle(options)
// expand(options)
// collapse(options)
//
// Events:
//
// expand: Triggered when the option header is expanded
// collapse: Triggered when the option header is collapsed
//
(function ($, undefined) {
$.widget("tizen.optionheader", $.mobile.widget, {
options: {
initSelector: ":jqmData(role='optionheader')",
showIndicator: true,
theme: 's',
startCollapsed: false,
expandable: true,
duration: 0.25,
collapseOnInit : true,
default_font_size : $('html').css('font-size')
},
collapsedHeight: '5px',
_create: function () {
var options,
theme,
self = this,
elementHeight = 106,
parentPage,
dataOptions = this.element.jqmData( 'options' ),
page = this.element.closest( ':jqmData(role="page")' );
// parse data-options
$.extend( this.options, dataOptions );
this.isCollapsed = this.options.collapseOnInit;
this.expandedHeight = null;
// parse data-theme and reset options.theme if it's present
theme = this.element.jqmData( 'theme' ) || this.options.theme;
this.options.theme = theme;
this.element.closest( ':jqmData(role="header")' ).addClass( "ui-option-header-resizing" );
// set up the click handler; it's done here so it can
// easily be removed, as there should only be one instance
// of the handler function for each class instance
this.clickHandler = function () {
self.toggle();
};
/* Apply REM scaling */
elementHeight = elementHeight / ( 36 / parseInt(this.option.default_font_size) );
if ( this.element.height() < elementHeight ) {
this.element.css( "height", elementHeight );
}
// get the element's dimensions
// and to set its initial collapse state;
// either do it now (if the page is visible already)
// or on pageshow
if ( page.is(":visible") ) {
self.refresh();
self._realize();
} else {
self.refresh();
page.bind( "pagebeforeshow", function () {
self._setArrowLeft();
self._realize();
});
}
self._setArrowLeft();
// this.refresh();
},
_realize: function () {
if ( !this.expandedHeight ) {
this.expandedHeight = this.element.height();
}
if ( this.isCollapsed ) {
// if (this.options.startCollapsed) {
this.collapse( {duration: 0} );
}
},
_setArrowLeft: function () {
var matchingBtn = $( this.element ).jqmData( "for" ),
arrowCenter = 14,
btn2Position = 10,
btn3Position = 144,
matchBtn = $( this.element ).parents( ".ui-page" ).find( "#" + matchingBtn ),
buttonRight = matchBtn.nextAll().is( "a" ) ? btn3Position : btn2Position;
/* Apply REM scaling */
scaleFactor = ( 36 / parseInt(this.option.default_font_size) );
if ( $(this.element).parents(".ui-page").find( "#" + matchingBtn ).length != 0 ) {
if ( this.options.expandable ) {
matchBtn.bind( 'vclick', this.clickHandler );
} else {
matchBtn.unbind( 'vclick', this.clickHandler );
}
// decide arrow Button position
if ( matchBtn.css( "left" ) && matchBtn.css( "left" ) != "auto" ) {
$( ".ui-triangle-image" ).css( "left", matchBtn.width() / 2 + parseInt(matchBtn.css( "left" ), 10) - ( arrowCenter / scaleFactor ) + "px" );
} else if ( matchBtn.css("right") ) {
$( ".ui-triangle-image" ).css( "left", document.documentElement.clientWidth - matchBtn.width() / 2 - ( ( buttonRight - arrowCenter ) / scaleFactor ) + "px" );
}
} else {
$( ".ui-triangle-image" ).css( "left", document.documentElement.clientWidth / 2 - ( arrowCenter / scaleFactor ) + "px" );
}
},
// Draw the option header, according to current options
refresh: function () {
var el = this.element,
arrow = $( '<div class="ui-option-header-triangle-arrow"></div>' ),
optionHeaderClass = 'ui-option-header',
gridRowSelector = '.ui-grid-a,.ui-grid-b,.ui-grid-c,.ui-grid-d,.ui-grid-e',
theme = this.options.theme,
numRows,
rowsClass,
themeClass,
klass,
o = $.extend( {grid: null} ),
$kids = el.find( "div" ).eq( 0 ).children().children(),
letter,
gridCols = {solo: 1, a: 2, b: 3, c: 4, d: 5},
grid = o.grid;
if ( !grid ) {
if ( $kids.length <= 5 ) {
for ( letter in gridCols ) {
if ( gridCols[ letter ] === $kids.length ) {
grid = letter;
}
}
numRows = $kids.length / gridCols[grid];
} else {
numRows = 2;
}
}
// count ui-grid-* elements to get number of rows
// numRows = el.find(gridRowSelector).length;
// ...at least one row
// numRows = Math.max(1, numRows);
// add classes to outer div:
// ui-option-header-N-row, where N = options.rows
// ui-bar-X, where X = options.theme (defaults to 'c')
// ui-option-header
rowsClass = 'ui-option-header-' + numRows + '-row';
themeClass = 'ui-body-' + this.options.theme;
el.removeClass( rowsClass ).addClass( rowsClass );
el.removeClass( themeClass ).addClass( themeClass );
el.removeClass( optionHeaderClass ).addClass( optionHeaderClass );
// remove any arrow currently visible
el.prev( '.ui-option-header-triangle-arrow' ).remove();
// el.prev('.ui-triangle-container').remove();
// if there are elements inside the option header
// and this.options.showIndicator,
// insert a triangle arrow as the first element inside the
// optionheader div to show the header has hidden content
if ( this.options.showIndicator ) {
el.before( arrow );
arrow.append("<div class='ui-triangle-image'></div>");
// arrow.triangle({"color": el.css('background-color'), offset: "50%"});
}
// if expandable, bind clicks to the toggle() method
if ( this.options.expandable ) {
// el.unbind('vclick', this.clickHandler).bind('vclick', this.clickHandler);
// arrow.unbind('vclick', this.clickHandler).bind('vclick', this.clickHandler);
el.bind( 'vclick', this.clickHandler );
arrow.bind( 'vclick', this.clickHandler );
} else {
el.unbind( 'vclick', this.clickHandler );
arrow.unbind( 'vclick', this.clickHandler );
}
// for each ui-grid-a element, add a class ui-option-header-row-M
// to it, where M is the xpath position() of the div
/* el.find(gridRowSelector).each(function (index) {
var klass = 'ui-option-header-row-' + (index + 1);
$(this).removeClass(klass).addClass(klass);
});*/
klass = 'ui-option-header-row-' + ( numRows );
el.find( "div" ).eq( 0 ).removeClass( klass ).addClass( klass );
// redraw the buttons (now that the optionheader has the right
// swatch)
el.find( '.ui-btn' ).each(function () {
$( this ).attr( 'data-' + $.mobile.ns + 'theme', theme );
// hack the class of the button to remove the old swatch
var klass = $( this ).attr( 'class' );
klass = klass.replace(/ui-btn-up-\w{1}\s*/, '');
klass = klass + ' ui-btn-up-' + theme;
$( this ).attr( 'class', klass );
});
},
_setHeight: function ( height, isCollapsed, options ) {
var self = this,
elt = this.element.get( 0 ),
duration,
commonCallback,
callback,
handler;
options = options || {};
// set default duration if not specified
duration = options.duration;
if ( typeof duration == 'undefined' ) {
duration = this.options.duration;
}
// the callback to always call after expanding or collapsing
commonCallback = function () {
self.isCollapsed = isCollapsed;
if ( isCollapsed ) {
self.element.trigger( 'collapse' );
} else {
self.element.trigger( 'expand' );
}
};
// combine commonCallback with any user-specified callback
if ( options.callback ) {
callback = function () {
options.callback();
commonCallback();
};
} else {
callback = function () {
commonCallback();
};
}
// apply the animation
if ( duration > 0 && $.support.cssTransitions ) {
// add a handler to invoke a callback when the animation is done
handler = {
handleEvent: function ( e ) {
elt.removeEventListener( 'webkitTransitionEnd', this );
self.element.css( '-webkit-transition', null );
callback();
}
};
elt.addEventListener( 'webkitTransitionEnd', handler, false );
// apply the transition
this.element.css( '-webkit-transition', 'height ' + duration + 's ease-out' );
this.element.css( 'height', height );
} else {
// make sure the callback gets called even when there's no
// animation
this.element.css( 'height', height );
callback();
}
},
/**
* Toggle the expanded/collapsed state of the widget.
* {Object} [options] Configuration for the expand/collapse
* {Integer} [options.duration] Duration of the expand/collapse;
* defaults to this.options.duration
* {Function} options.callback Function to call after toggle completes
*/
toggle: function ( options ) {
var toggle_header = this.element.parents( ":jqmData(role='header')" ),
toggle_content = this.element.parents( ":jqmData(role='page')" ).find( ".ui-content" ),
CollapsedTop = 110,
ExpandedTop = 206,
CalculateTime,
/* Apply REM scaling */
scaleFactor = ( 36 / parseInt($('html').css('font-size')));
if ( toggle_header.children().is( ".input-search-bar" ) ) {
CollapsedTop = 218;
ExpandedTop = 314;
}
/* Scale Factor */
CollapsedTop = ( CollapsedTop / scaleFactor );
ExpandedTop = ( ExpandedTop / scaleFactor );
if ( $( window ).scrollTop() <= CollapsedTop ) {
toggle_header.css( "position", "relative" );
toggle_content.css( "top", "0px" );
}
if ( this.isCollapsed ) {
this.expand( options );
if ( $( window ).scrollTop() <= ExpandedTop ) {
CalculateTime = setTimeout( function () {
toggle_header.css( 'position', 'fixed' );
toggle_content.css( 'top', ExpandedTop + "px" );
}, 500 );
} else {
// Need to move scroll top
toggle_header.css( 'position', 'fixed' );
toggle_content.css( 'top', ExpandedTop + "px" );
}
this.options.collapseOnInit = false;
} else {
this.collapse( options );
if ( $(window).scrollTop() <= ExpandedTop ) {
CalculateTime = setTimeout( function () {
toggle_header.css( 'position', 'fixed' );
toggle_content.css( 'top', CollapsedTop + "px" );
}, 500 );
} else {
toggle_header.css( 'position', 'fixed' );
toggle_content.css( 'top', CollapsedTop + "px" );
}
}
this.options.collapseOnInit = true;
},
_setDisabled: function ( value ) {
$.Widget.prototype._setOption.call( this, "disabled", value );
this.element.add( this.element.prev( ".ui-triangle-container" ) )[value ? "addClass" : "removeClass"]("ui-disabled");
},
/**
* Takes the same options as toggle()
*/
collapse: function ( options ) {
var collapsedBarHeight = 10,
scaleFactor = ( 36 / parseInt($('html').css('font-size')));
collapsedBarHeight = collapsedBarHeight / scaleFactor;
// if (!this.isCollapsed) {
this._setHeight( collapsedBarHeight + "px", true, options );
// }
},
/**
* Takes the same options as toggle()
*/
expand: function ( options ) {
// if (this.isCollapsed) {
this._setHeight( this.expandedHeight, false, options );
// }
}
});
// auto self-init widgets
$(document).bind("pagecreate create", function ( e ) {
$($.tizen.optionheader.prototype.options.initSelector, e.target)
.not(":jqmData(role='none'), :jqmData(role='nojs')")
.optionheader();
});
}(jQuery) );
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Author: Youmin Ha <youmin.ha@samsung.com>
*/
/**
* Pagecontrol widget shows number bullets, receives touch event for each bullet,
* and runs your callback for each touch event.
*
* HTML Attributes:
*
* Pagecontrol widget uses <div> element as an element itself. It takes following attributes.
*
* data-role: This widget must have 'pagecontrol' as data-role value.
* data-max: Maximum nimber of pagecontrol bullets. This property must not exceed 10.
* data-initVal: Initially selected value of the pagecontrol widget. Must between 1 and data-max. If this attribute is not given, initial value is set to 1.
*
* APIs:
*
* setValue( value )
* : Set current value. Actually triggers 'change' event to the widget with given value.
* @param[in] value A value to be changed.
*
* getValue( )
* : Get current value.
* @return Current value.
*
* Events:
*
* change: Raised when a value is changed, by setting it by javascript, or by user's touch event.
*
* Examples:
*
* <div id="foo" data-role="pagecontrol" data-max="10"></div>
* ...
* <script language="text/javascript">
*
* // Bind callback to value change
* $('foo').bind('change', function (event, value) {
* // event: 'change'
* // value: changed value
* });
*
* // Set a value to 3
* $('foo').trigger('change', 3);
* </script>
*/
(function ($, undefined) {
$.widget( "tizen.pagecontrol", $.mobile.widget, {
options: {
initSelector: ":jqmData(role='pagecontrol')"
},
_create: function ( ) {
},
_init: function ( ) {
var self = this,
e = this.element,
maxVal = e.data( "max" ),
currentVal = e.attr( "data-initVal" ),
i = 0,
btn = null,
buf = null,
page_margin_class = 'page_n_margin_44';
// Set default values
if ( ! maxVal ) {
maxVal = 1;
} else if ( maxVal > 10 ) {
maxVal = 10;
}
e.data( "max", maxVal );
if ( ! currentVal ) {
currentVal = 1;
}
e.data( "current", currentVal );
// Set pagecontrol class
e.addClass( 'pagecontrol' );
// Set empty callback variable
self.changeCallback = null;
// Calculate left/right margin
if ( maxVal <= 7 ) {
page_margin_class = 'page_n_margin_44';
} else if ( maxVal == 8 ) {
page_margin_class = 'page_n_margin_35';
} else if ( maxVal == 9 ) {
page_margin_class = 'page_n_margin_26';
} else {
page_margin_class = 'page_n_margin_19';
}
// subroutine: find a child by value
function getBtn( value ) {
return e.children( ":jqmData(value='" + value + "')" );
}
// subroutine: change active button by value
function changeActiveBtn( newNum ) {
var oldNum = e.data( 'current' );
// Check value
if ( newNum < 1 || newNum > e.max ) {
return false;
}
getBtn( oldNum ).removeClass( 'page_n_' + oldNum )
.addClass( 'page_n_dot' );
getBtn( newNum ).removeClass( 'page_n_dot' )
.addClass( 'page_n_' + newNum );
}
function triggerChange( event ) {
// Trigger change event
e.trigger( 'change', $( this ).data( 'value' ) );
}
// Add dot icons
for ( i = 1; i <= maxVal; i++ ) {
btn = $( '<div class="page_n page_n_dot ' + page_margin_class + '" data-value="' + i + '"></div>' );
e.append( btn );
if ( i == currentVal ) {
btn.removeClass( 'page_n_dot' )
.addClass( 'page_n_' + i );
}
// bind vclick event to each icon
btn.bind( 'vclick', triggerChange );
}
// pagecontrol element's change event
e.bind( 'change', function ( event, value ) {
// 1. Change activated button
changeActiveBtn( value );
// 2. Store new value (DO NOT change this order!)
e.data( 'current', value );
});
}
}); // end: $.widget()
$( document ).bind( "pagecreate create", function ( e ) {
$( $.tizen.pagecontrol.prototype.options.initSelector, e.target )
.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
.pagecontrol( );
});
} ( jQuery ) );
/*
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (c) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*/
// pagelist widget
//
// Given an element, this widget collects all links contained in the descendants of the element and constructs
// a popupwindow widget containing numbered buttons for each encountered link.
//
// You can mark any one element in your document with "data-pagelist='true'" and a pagelist will be created that
// will allow the user to navigate between the pages linked to within the element.
//
// Currently, only one pagelist can exist in a document and, once created, it cannot be modified.
(function ( $, undefined ) {
window.ensureNS( "jQuery.mobile.tizen" );
$.widget( "tizen.pagelist", $.tizen.widgetex, {
_htmlProto: {
source:
$("<div><div id='pagelist' class='ui-pagelist' data-role='popupwindow' data-shadow='false' data-overlayTheme=''>" +
" <a id='pagelist-button' data-role='button' data-inline='true'></a>" +
" <br id='pagelist-rowbreak'></br>" +
"</div>" +
"</div>")
, ui: {
pageList: "#pagelist",
button: "#pagelist-button",
rowBreak: "#pagelist-rowbreak"
}
},
_create: function () {
var self = this,
popPageList = false,
idx = 0;
this._ui.button.remove();
this._ui.rowBreak.remove();
this._ui.pageList
.appendTo( $( "body" ) )
.popupwindow()
.bind( "vclick", function ( e ) {
$( this ).popupwindow( "close" );
} );
this.element.find( "a[href]" ).each( function ( elemIdx, elem ) {
if ( idx > 0 && ( ( idx % 10 ) != 0 ) ) {
self._ui.pageList.append( self._ui.rowBreak.clone() );
}
self._ui.button
.clone()
.attr( "href", $( elem ).attr( "href" ) )
.text( ++idx )
.appendTo( self._ui.pageList )
.buttonMarkup()
.bind( "vclick", function () { self._ui.pageList.popupwindow( "close" ); } )
.find( ".ui-btn-inner" )
.css( { padding: 2 } );
} );
$( document ).bind( "keydown", function ( e ) {
popPageList = ( e.keyCode === $.mobile.keyCode.CONTROL );
} );
$( document ).bind( "keyup", function ( e ) {
if ( e.keyCode === $.mobile.keyCode.CONTROL && popPageList ) {
var maxDim = { cx: 0, cy: 0 };
self._ui.pageList.popupwindow( "open", undefined, 0 );
self._ui.pageList.find( "a" )
.each( function () {
var btn = $( this ),
dim = {
cx: btn.outerWidth( true ),
cy: btn.outerHeight( true )
};
// Make sure things will be even later, because padding cannot have decimals - apparently :-S
if ( dim.cx % 2 ) {
btn.css( "padding-left", parseInt( btn.css( "padding-left" ), 10 ) + 1 );
}
if ( dim.cy % 2 ) {
btn.css( "padding-bottom", parseInt( btn.css( "padding-bottom" ), 10 ) + 1 );
}
maxDim.cx = Math.max( maxDim.cx, dim.cx );
maxDim.cy = Math.max( maxDim.cy, dim.cy );
} )
.each( function () {
var padding = {
h: Math.max( 0, ( maxDim.cx - $( this ).outerWidth( true ) ) / 2 ),
v: Math.max( 0, ( maxDim.cy - $( this ).outerHeight( true ) ) / 2 )
},
btn = $( this ),
inner = btn.find( ".ui-btn-inner" );
inner.css( {
"padding-left" : parseInt( inner.css( "padding-left" ), 10 ) + padding.h,
"padding-top" : parseInt( inner.css( "padding-top" ), 10 ) + padding.v,
"padding-right" : parseInt( inner.css( "padding-right" ), 10 ) + padding.h,
"padding-bottom" : parseInt( inner.css( "padding-bottom" ), 10 ) + padding.v
} );
btn[( ( btn.attr( "href" ) === "#" + $.mobile.activePage.attr( "id" ) ) ? "addClass" : "removeClass" )]( "ui-btn-active" );
} );
e.stopPropagation();
e.preventDefault();
}
popPageList = false;
} );
}
} );
// Look for an element marked as a pagelist and assign $.mobile.tizen.pagelist with a newly created pagelist.
// If $.mobile.tizen.pagelist is already assigned, ignore any new "data-pagelist='true'" designations.
$( document ).bind( "pagecreate create", function ( e ) {
$( ":jqmData(pagelist='true')", e.target )
.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
.each( function () {
if ( $.mobile.tizen.pagelist === undefined ) {
$.extend( $.mobile.tizen, {
pagelist: $( this ).pagelist()
} );
}
return false;
} );
} );
}( jQuery ) );
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
* Copyright (c) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Gabriel Schulhof <gabriel.schulhof@intel.com>,
* Elliot Smith <elliot.smith@intel.com>
*/
// Shows other elements inside a popup window.
//
// To apply, add the attribute data-role="popupwindow" to a <div> element inside
// a page. Alternatively, call popupwindow()
// on an element, eg :
//
// $("#mypopupwindowContent").popupwindow();
// where the html might be :
// <div id="mypopupwindowContent"></div>
//
// To trigger the popupwindow to appear, it is necessary to make a call to its
// 'open()' method. This is typically done by binding a function to an event
// emitted by an input element, such as a the clicked event emitted by a button
// element. The open() method takes two arguments, specifying the x and y
// screen coordinates of the center of the popup window.
// You can associate a button with a popup window like this:
// <div id="mypopupContent" style="display: table;" data-role="popupwindow">
// <table>
// <tr> <td>Eenie</td> <td>Meenie</td> <td>Mynie</td> <td>Mo</td> </tr>
// <tr> <td>Catch-a</td> <td>Tiger</td> <td>By-the</td> <td>Toe</td> </tr>
// <tr> <td>If-he</td> <td>Hollers</td> <td>Let-him</td> <td>Go</td> </tr>
// <tr> <td>Eenie</td> <td>Meenie</td> <td>Mynie</td> <td>Mo</td> </tr>
// </table>
// </div>
// <a href="#myPopupContent" data-rel="popupwindow" data-role="button">Show popup</a>
//
// Options:
//
// theme: String; the theme for the popupwindow contents
// Default: null
//
// overlayTheme: String; the theme for the popupwindow
// Default: null
//
// shadow: Boolean; display a shadow around the popupwindow
// Default: true
//
// corners: Boolean; display a shadow around the popupwindow
// Default: true
//
// fade: Boolean; fades the opening and closing of the popupwindow
//
// transition: String; the transition to use when opening or closing
// a popupwindow
// Default: $.mobile.defaultDialogTransition
//
// Events:
// close: Emitted when the popupwindow is closed.
(function ( $, undefined ) {
$.widget( "tizen.popupwindow", $.tizen.widgetex, {
options: {
theme: null,
overlayTheme: "s",
style: "custom",
disabled: false,
shadow: true,
corners: true,
fade: true,
widthRatio: 0.8612,
transition: $.mobile.defaultDialogTransition,
initSelector: ":jqmData(role='popupwindow')"
},
_htmlProto: {
source:
$("<div><div>" +
" <div id='popupwindow-screen' class='ui-selectmenu-screen ui-screen-hidden ui-popupwindow-screen'></div>" +
" <div id='popupwindow-container' class='ui-popupwindow ui-popupwindow-padding ui-selectmenu-hidden ui-overlay-shadow ui-corner-all'></div>" +
"</div>" +
"</div>")
, ui: {
screen: "#popupwindow-screen",
container: "#popupwindow-container"
}
},
_create: function () {
var thisPage = this.element.closest(":jqmData(role='page')"),
self = this,
popup = this.element,
o = this.options,
style = popup.attr( 'data-style' );
if (thisPage.length === 0) {
thisPage = $("body");
}
// Drop a placeholder into the location from which we shall rip out the popup window contents
this._ui.placeholder =
$("<div><!-- placeholder" +
(this.element.attr("id") === undefined
? ""
: " for " + this.element.attr("id")) + " --></div>")
.css("display", "none")
.insertBefore(this.element);
// Apply the proto
thisPage.append(this._ui.screen);
this._ui.container.insertAfter(this._ui.screen);
this._ui.container.append(this.element);
// Define instance variables
$.extend( self, {
_isOpen: false
});
//Data Style Start
if (style) {
o.style = style;
}
popup.addClass( o.style );
popup.find( ":jqmData(role='title')" )
.wrapAll( "<div class='popup-title'></div>" );
popup.find( ":jqmData(role='text')" )
.wrapAll( "<div class='popup-text'></div>" );
popup.find( ":jqmData(role='button-bg')" )
.wrapAll( "<div class='popup-button-bg'></div>" );
popup.find( ":jqmData(role='check-bg')" )
.wrapAll( "<div class='popup-check-bg'></div>" );
popup.find( ":jqmData(role='scroller-bg')" )
.wrapAll( "<div class='popup-scroller-bg'></div>" );
popup.find( ":jqmData(role='text-bottom-bg')" )
.wrapAll( "<div class='popup-text-bottom-bg'></div>" );
popup.find( ":jqmData(role='text-left')" )
.wrapAll( "<div class='popup-text-left'></div>" );
popup.find( ":jqmData(role='text-right')" )
.wrapAll( "<div class='popup-text-right'></div>" );
popup.find( ":jqmData(role='progress-bg')" )
.wrapAll( "<div class='popup-progress-bg'></div>" );
//Data Style End
// Events on "screen" overlay
this._ui.screen.bind( "vclick", function (event) {
self.close();
});
},
_realSetTheme: function (dst, theme) {
var classes = (dst.attr("class") || "").split(" "),
alreadyAdded = true,
currentTheme = null,
matches;
while (classes.length > 0) {
currentTheme = classes.pop();
matches = currentTheme.match(/^ui-body-([a-z])$/);
if (matches && matches.length > 1) {
currentTheme = matches[1];
break;
} else {
currentTheme = null;
}
}
dst.removeClass("ui-body-" + currentTheme);
if ((theme || "").match(/[a-z]/)) {
dst.addClass("ui-body-" + theme);
}
},
_setTheme: function (value) {
this._realSetTheme(this.element, value);
this.options.theme = value;
this.element.attr("data-" + ($.mobile.ns || "") + "theme", value);
},
_setOverlayTheme: function (value) {
this._realSetTheme(this._ui.container, value);
// The screen must always have some kind of background for fade to work, so, if the theme is being unset,
// set the background to "a".
this._realSetTheme(this._ui.screen, (value === "" ? "a" : value));
this.options.overlayTheme = value;
this.element.attr("data-" + ($.mobile.ns || "") + "overlay-theme", value);
},
_setShadow: function (value) {
this.options.shadow = value;
this.element.attr("data-" + ($.mobile.ns || "") + "shadow", value);
this._ui.container[value ? "addClass" : "removeClass"]("ui-overlay-shadow");
},
_setCorners: function (value) {
this.options.corners = value;
this.element.attr("data-" + ($.mobile.ns || "") + "corners", value);
this._ui.container[value ? "addClass" : "removeClass"]("ui-corner-all");
},
_setFade: function (value) {
this.options.fade = value;
this.element.attr("data-" + ($.mobile.ns || "") + "fade", value);
},
_setTransition: function (value) {
this._ui.container
.removeClass((this.options.transition || ""))
.addClass(value);
this.options.transition = value;
this.element.attr("data-" + ($.mobile.ns || "") + "transition", value);
},
_setDisabled: function (value) {
$.Widget.prototype._setOption.call(this, "disabled", value);
if (value) {
this.close();
}
},
_placementCoords: function (x, y, cx, cy) {
// Try and center the overlay over the given coordinates
var ret,
scrollTop = $(window).scrollTop(),
screenHeight = $(window).height(),
screenWidth = $(window).width(),
halfheight = cy / 2,
maxwidth = parseFloat( this._ui.container.css( "max-width" ) ),
roomtop = y - scrollTop,
roombot = scrollTop + screenHeight - y,
newtop,
newleft;
if ( roomtop > cy / 2 && roombot > cy / 2 ) {
newtop = y - halfheight;
} else {
// 30px tolerance off the edges
newtop = roomtop > roombot ? scrollTop + screenHeight - cy - 30 : scrollTop + 30;
}
// If the menuwidth is smaller than the screen center is
if ( cx < maxwidth ) {
newleft = ( screenWidth - cx ) / 2;
} else {
//otherwise insure a >= 30px offset from the left
newleft = x - cx / 2;
// 10px tolerance off the edges
if ( newleft < 10 ) {
newleft = 10;
} else if ( ( newleft + cx ) > screenWidth ) {
newleft = screenWidth - cx - 10;
}
}
return { x : newleft, y : newtop };
},
destroy: function () {
// Put the element back where we ripped it out from
this.element.insertBefore(this._ui.placeholder);
// Clean up
this._ui.placeholder.remove();
this._ui.container.remove();
this._ui.screen.remove();
this.element.triggerHandler("destroyed");
$.Widget.prototype.destroy.call(this);
},
open: function (x_where, y_where) {
if (!(this._isOpen || this.options.disabled)) {
var self = this,
x = (undefined === x_where ? $(window).width() / 2 : x_where),
y = (undefined === y_where ? $(window).height() / 2 : y_where),
coords,
zIndexMax = 0,
ctxpopup = this.element.data("ctxpopup"),
popupWidth,
menuHeight,
menuWidth,
scrollTop,
screenHeight,
screenWidth,
roomtop,
roombot,
halfheight,
maxwidth,
newtop,
newleft;
if ( !ctxpopup ) {
popupWidth = $(window).width() * this.options.widthRatio;
this._ui.container.css("width", popupWidth);
// If the width of the popup exceeds the width of the window, we need to limit the width here,
// otherwise outer{Width,Height}(true) below will happily report the unrestricted values, causing
// the popup to get placed wrong.
if (this._ui.container.outerWidth(true) > $(window).width()) {
this._ui.container.css({"max-width" : $(window).width() - 30});
}
}
coords = this._placementCoords(x, y,
this._ui.container.outerWidth(true),
this._ui.container.outerHeight(true));
$(document)
.find("*")
.each(function () {
var el = $(this),
zIndex = parseInt(el.css("z-index"), 10);
if (!(el.is(self._ui.container) || el.is(self._ui.screen) || isNaN(zIndex))) {
zIndexMax = Math.max(zIndexMax, zIndex);
}
});
this._ui.screen
.height($(document).height())
.removeClass("ui-screen-hidden");
if (this.options.fade) {
this._ui.screen.animate({opacity: 0.5}, "fast");
} else {
this._ui.screen.css({opacity: 0.0});
}
//Recalculate popup position
menuHeight = this._ui.container.innerHeight(true);
menuWidth = this._ui.container.innerWidth(true);
scrollTop = $(window).scrollTop();
screenHeight = $(window).height();
screenWidth = $(window).width();
roomtop = y - scrollTop;
roombot = scrollTop + screenHeight - y;
halfheight = menuHeight / 2;
maxwidth = parseFloat( this._ui.container.css( "max-width" ) );
newtop = (screenHeight - menuHeight) / 2 + scrollTop;
if ( menuWidth < maxwidth ) {
newleft = ( screenWidth - menuWidth ) / 2;
} else {
//otherwise insure a >= 30px offset from the left
newleft = x - menuWidth / 2;
// 30px tolerance off the edges
if ( newleft < 30 ) {
newleft = 30;
} else if ( ( newleft + menuWidth ) > screenWidth ) {
newleft = screenWidth - menuWidth - 30;
}
}
//Recalculate popup position End
if ( ctxpopup ) {
newtop = coords.y;
newleft = coords.x;
}
this._ui.container
.removeClass("ui-selectmenu-hidden")
.css({
top: newtop,
left: newleft
})
.addClass("in")
.animationComplete(function () {
self._ui.screen.height($(document).height());
});
this._isOpen = true;
}
},
close: function () {
if (this._isOpen) {
var self = this,
hideScreen = function () {
self._ui.screen.addClass("ui-screen-hidden");
self._isOpen = false;
self.element.trigger("closed");
};
this._ui.container
.removeClass("in")
.addClass("reverse out")
.animationComplete(function () {
self._ui.container
.removeClass("reverse out")
.addClass("ui-selectmenu-hidden")
.removeAttr("style");
});
if (this.options.fade) {
this._ui.screen.animate({opacity: 0.0}, "fast", hideScreen);
} else {
hideScreen();
}
}
}
});
$.tizen.popupwindow.bindPopupToButton = function (btn, popup) {
if (btn.length === 0 || popup.length === 0) {
return;
}
var btnVClickHandler = function (e) {
// When /this/ button causes a popup, align the popup's theme with that of the button, unless the popup has a theme pre-set
if (!popup.jqmData("overlay-theme-set")) {
popup.popupwindow("option", "overlayTheme", btn.jqmData("theme"));
}
popup.popupwindow("open",
btn.offset().left + btn.outerWidth() / 2,
btn.offset().top + btn.outerHeight() / 2);
// Swallow event, because it might end up getting picked up by the popup window's screen handler, which
// will in turn cause the popup window to close - Thanks Sasha!
if (e.stopPropagation) {
e.stopPropagation();
}
if (e.preventDefault) {
e.preventDefault();
}
};
// If the popup has a theme set, prevent it from being clobbered by the associated button
if ((popup.popupwindow("option", "overlayTheme") || "").match(/[a-z]/)) {
popup.jqmData("overlay-theme-set", true);
}
btn
.attr({
"aria-haspopup": true,
"aria-owns": btn.attr("href")
})
.removeAttr("href")
.bind("vclick", btnVClickHandler);
popup.bind("destroyed", function () {
btn.unbind("vclick", btnVClickHandler);
});
};
$(document).bind("pagecreate create", function (e) {
$($.tizen.popupwindow.prototype.options.initSelector, e.target)
.not(":jqmData(role='none'), :jqmData(role='nojs')")
.popupwindow();
$("a[href^='#']:jqmData(rel='popupwindow')", e.target).each(function () {
$.tizen.popupwindow.bindPopupToButton($(this), $($(this).attr("href")));
});
});
}(jQuery));
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
* Copyright (c) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Gabriel Schulhof <gabriel.schulhof@intel.com>
*/
// This widget is implemented in an extremely ugly way. It should derive from $.tizen.popupwindow, but it doesn't
// because there's a bug in jquery.ui.widget.js which was fixed in jquery-ui commit
// b9153258b0f0edbff49496ed16d2aa93bec07d95. Once a version of jquery-ui containing that commit is released
// (probably >= 1.9m5), and jQuery Mobile picks up the widget from there, this widget needs to be rewritten properly.
// The problem is that, when a widget inherits from a superclass and declares an object in its prototype identical in key
// to one in the superclass, upon calling $.widget the object is overwritten in both the prototype of the superclass and
// the prototype of the subclass. The prototype of the superclass should remain unchanged.
(function ( $, undefined ) {
$.widget( "tizen.ctxpopup", $.tizen.widgetex, {
options: $.extend( {}, $.tizen.popupwindow.prototype.options, {
initSelector: ":not(:not(" + $.tizen.popupwindow.prototype.options.initSelector + ")):not(:not(:jqmData(show-arrow='true'), :jqmData(show-arrow)))"
} ),
_htmlProto: {
source:
$("<div><div id='outer' class='ui-ctxpopup'>" +
" <div id='top' class='ui-ctxpopup-row' data-role='triangle' data-location='top'></div>" +
" <div class='ui-ctxpopup-row'>" +
" <div id='left' class='ui-ctxpopup-cell' data-role='triangle' data-location='left'></div>" +
" <div id='container' class='ui-ctxpopup-cell'></div>" +
" <div id='right' class='ui-ctxpopup-cell' data-role='triangle' data-location='right'></div>" +
" </div>" +
" <div id='bottom' class='ui-ctxpopup-row' data-role='triangle' data-location='bottom'></div>" +
"</div>" +
"</div>")
, ui: {
outer : "#outer",
container : "#container", // the key has to have the name "container"
arrow : {
all : ":jqmData(role='triangle')",
l : "#left",
t : "#top",
r : "#right",
b : "#bottom"
}
}
},
_create: function () {
if ( !this.element.data( "popupwindow" ) ) {
this.element.popupwindow();
}
this.element.data( "popupwindow" )
._ui.container
.removeClass( "ui-popupwindow-padding" )
.append( this._ui.outer );
this._ui.outer.trigger( "create" ); // Creates the triangle widgets
this._ui.container
.addClass( "ui-popupwindow-padding" )
.append( this.element );
},
_setOption: function ( key, value ) {
$.tizen.popupwindow.prototype._setOption.apply( this.element.data( "popupwindow" ), arguments );
this.options[key] = value;
}
} );
var origOpen = $.tizen.popupwindow.prototype.open,
orig_setOption = $.tizen.popupwindow.prototype._setOption,
orig_placementCoords = $.tizen.popupwindow.prototype._placementCoords;
$.tizen.popupwindow.prototype._setOption = function ( key, value ) {
var ctxpopup = this.element.data( "ctxpopup" ),
needsApplying = true,
origContainer;
if ( ctxpopup ) {
if ( "shadow" === key || "overlayTheme" === key || "corners" === key ) {
origContainer = this._ui.container;
this._ui.container = ctxpopup._ui.container;
orig_setOption.apply( this, arguments );
this._ui.container = origContainer;
needsApplying = false;
}
ctxpopup.options[key] = value;
}
if ( needsApplying ) {
orig_setOption.apply(this, arguments);
}
};
$.tizen.popupwindow.prototype._placementCoords = function ( x, y, cx, cy ) {
var ctxpopup = this.element.data( "ctxpopup" ),
self = this,
coords = {},
minDiff,
minDiffIdx;
function getCoords( arrow, x_factor, y_factor ) {
// Unhide the arrow we want to test to take it into account
ctxpopup._ui.arrow.all.hide();
ctxpopup._ui.arrow[arrow].show();
var isHorizontal = ( "b" === arrow || "t" === arrow ),
// Names of keys used in calculations depend on whether things are horizontal or not
coord = ( isHorizontal
? { point: "x", size: "cx", beg: "left", outerSize: "outerWidth", niceSize: "width", triangleSize : "height" }
: { point: "y", size: "cy", beg: "top", outerSize: "outerHeight", niceSize: "height", triangleSize : "width" } ),
size = {
cx : self._ui.container.width(),
cy : self._ui.container.height()
},
halfSize = {
cx : size.cx / 2,
cy : size.cy / 2
},
desired = {
"x" : x + halfSize.cx * x_factor,
"y" : y + halfSize.cy * y_factor
},
orig = orig_placementCoords.call( self, desired.x, desired.y, size.cx, size.cy ),
// The triangleOffset must be clamped to the range described below:
//
// +-------...
// | /\
// | / \
// ----+--+-,-----...
//lowerDiff -->____| |/ <-- possible rounded corner
//triangle size --> | /|
// ____|/ |
// ^ |\ | <-- lowest possible offset for triangle
// actual range of | | \|
// arrow offset | | |
// values due to | . . Payload table cell looks like
// possible rounded | . . a popup window, and it may have
// corners and arrow | . . arbitrary things like borders,
// triangle size - | | | shadows, and rounded corners.
// our clamp range | | /|
// _v__|/ |
//triangle size --> |\ | <-- highest possible offset for triangle
// ____| \|
//upperDiff --> | |\ <-- possible rounded corner
// ----+--+-'-----...
// | \ /
// | \/
// +-------...
//
// We calculate lowerDiff and upperDiff by considering the offset and width of the payload (this.element)
// versus the offset and width of the element enclosing the triangle, because the payload is inside
// whatever decorations (such as borders, shadow, rounded corners) and thus can give a reliable indication
// of the thickness of the combined decorations
arrowBeg = ctxpopup._ui.arrow[arrow].offset()[coord.beg],
arrowSize = ctxpopup._ui.arrow[arrow][coord.outerSize]( true ),
payloadBeg = self.element.offset()[coord.beg],
payloadSize = self.element[coord.outerSize]( true ),
triangleSize = ctxpopup._ui.arrow[arrow][coord.triangleSize](),
triangleOffset =
Math.max(
triangleSize // triangle size
+ Math.max( 0, payloadBeg - arrowBeg ), // lowerDiff
Math.min(
arrowSize // bottom
- triangleSize // triangle size
- Math.max( 0, arrowBeg + arrowSize - ( payloadBeg + payloadSize ) ), // upperDiff
arrowSize / 2 // arrow unrestricted offset
+ desired[coord.point]
- orig[coord.point]
- halfSize[coord.size]
)
),
// Triangle points here
final = {
"x": orig.x + ( isHorizontal ? triangleOffset : 0) + ("r" === arrow ? size.cx : 0),
"y": orig.y + (!isHorizontal ? triangleOffset : 0) + ("b" === arrow ? size.cy : 0)
},
ret = {
actual : orig,
triangleOffset : triangleOffset,
absDiff : Math.abs( x - final.x ) + Math.abs( y - final.y )
};
// Hide it back
ctxpopup._ui.arrow[arrow].hide();
return ret;
}
if ( ctxpopup ) {
// Returns:
// {
// absDiff: int
// triangleOffset: int
// actual: { x: int, y: int }
// }
coords = {
l : getCoords( "l", 1, 0 ),
r : getCoords( "r", -1, 0 ),
t : getCoords( "t", 0, 1 ),
b : getCoords( "b", 0, -1 )
};
$.each( coords, function ( key, value ) {
if ( minDiff === undefined || value.absDiff < minDiff ) {
minDiff = value.absDiff;
minDiffIdx = key;
}
} );
// Side-effect: show the appropriate arrow and move it to the right offset
ctxpopup._ui.arrow[minDiffIdx]
.show()
.triangle( "option", "offset", coords[minDiffIdx].triangleOffset );
return coords[minDiffIdx].actual;
}
return orig_placementCoords.call( this, x, y, cx, cy );
};
$.tizen.popupwindow.prototype.open = function ( x, y ) {
var ctxpopup = this.element.data( "ctxpopup" );
if ( ctxpopup ) {
this._setShadow( false );
this._setCorners( false );
this._setOverlayTheme( null );
this._setOption( "overlayTheme", ctxpopup.options.overlayTheme );
ctxpopup._ui.arrow.all.triangle( "option", "color", ctxpopup._ui.container.css( "background-color" ) );
// temporary
$( '.ui-popupwindow' ).css( 'background', 'none' );
}
origOpen.call( this, x, y );
};
//auto self-init widgets
$( document ).bind( "pagecreate create", function ( e ) {
var ctxpopups = $( $.tizen.ctxpopup.prototype.options.initSelector, e.target );
$.tizen.ctxpopup.prototype.enhanceWithin( e.target );
} );
}( jQuery ) );
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software" ),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*/
// progress
(function ( $, window, undefined) {
$.widget( "tizen.progress", $.mobile.widget, {
options: {
style: "circle",
running: false
},
_show: function () {
if ( !this.init ) {
$( this.element ).append( this.html );
this.init = true;
}
var style = this.options.style;
$( this.element ).addClass( "ui-progress-container-" + style + "-bg" );
$( this.element )
.find( ".ui-progress-" + style )
.addClass( this.runningClass );
},
_hide: function () {
$( this.element )
.find( ".ui-progress-" + this.options.style )
.removeClass( this.runningClass );
},
running: function ( newRunning ) {
// get value
if ( newRunning === undefined ) {
return this.options.running;
}
// set value
this._setOption( "running", newRunning );
return this;
},
_setOption: function ( key, value ) {
if ( key === "running" ) {
// normalize invalid value
if ( typeof value !== "boolean" ) {
window.alert( "running value MUST be boolean type!" );
return;
}
this.options.running = value;
this._refresh();
}
},
_refresh: function () {
if ( this.options.running ) {
this._show();
} else {
this._hide();
}
},
_create: function () {
var self = this,
element = this.element,
style = element.jqmData( "style" ),
runningClass;
if ( style ) {
this.options.style = style;
}
this.html = $( '<div class="ui-progress-container-' + style + '">' +
'<div class="ui-progress-' + style + '"></div>' +
'</div>' );
runningClass = "ui-progress-" + style + "-running";
$.extend( this, {
init: false,
runningClass: runningClass
} );
this._refresh();
}
} ); /* End of widget */
// auto self-init widgets
$( document ).bind( "pagecreate", function ( e ) {
$( e.target ).find( ":jqmData(role='progress')" ).progress();
} );
}(jQuery, this));
/*
* jQuery UI Progressbar @VERSION
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Progressbar
*
* Depends:
* jquery.ui.core.js
* jquery.ui.widget.js
* Original file:
* jquery.ui.progressbar.js
*/
/* This is from jquery ui plugin - progressbar 11/16/2011 */
(function ( $, window, undefined ) {
$.widget( "tizen.progressbar", $.mobile.widget, {
options: {
value: 0,
max: 100
},
min: 0,
_create: function () {
this.element
.addClass( "ui-progressbar" )
.attr( {
role: "progressbar",
"aria-valuemin": this.min,
"aria-valuemax": this.options.max,
"aria-valuenow": this._value()
} );
this.valueDiv = $( "<div class='ui-progressbar-value'></div>" )
.appendTo( this.element );
this.oldValue = this._value();
this._refreshValue();
},
_destroy: function () {
this.element
.removeClass( "ui-progressbar" )
.removeAttr( "role" )
.removeAttr( "aria-valuemin" )
.removeAttr( "aria-valuemax" )
.removeAttr( "aria-valuenow" );
this.valueDiv.remove();
},
value: function ( newValue ) {
if ( newValue === undefined ) {
return this._value();
}
this._setOption( "value", newValue );
return this;
},
_setOption: function ( key, value ) {
if ( key === "value" ) {
this.options.value = value;
this._refreshValue();
if ( this._value() === this.options.max ) {
this._trigger( "complete" );
}
}
// jquery.ui.widget.js MUST be updated to new version!
//this._super( "_setOption", key, value );
},
_value: function () {
var val = this.options.value;
// normalize invalid value
if ( typeof val !== "number" ) {
val = 0;
}
return Math.min( this.options.max, Math.max( this.min, val ) );
},
_percentage: function () {
return 100 * this._value() / this.options.max;
},
_refreshValue: function () {
var value = this.value(),
percentage = this._percentage();
if ( this.oldValue !== value ) {
this.oldValue = value;
this._trigger( "change" );
}
this.valueDiv
.toggle( value > this.min )
.width( percentage.toFixed(0) + "%" );
this.element.attr( "aria-valuenow", value );
}
} );
// auto self-init widgets
$( document ).bind( "pagecreate", function ( e ) {
$( e.target ).find( ":jqmData(role='progressbar')" ).progressbar();
} );
}( jQuery, this ) );
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*/
/*
* jQuery Mobile Framework : "textinput" plugin for text inputs, textareas
* Copyright (c) jQuery Project
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
* Authors: Jinhyuk Jun <jinhyuk.jun@samsung.com>
* Wongi Lee <wongi11.lee@samsung.com>
*/
/**
* Searchbar can be created using <input> element with type=search
* <input type="search" name="search" id="search1" value="" />
*
* Searchbar can be inserted 3 cases
* content : seachbar behave same as content element
* header : searchbar placed below title(header), It doesn't move when scrolling page
* inside optionheader : Searchbar placed inside optionheader, searchbar can be seen only expand optionheader
*
* Examples:
*
* HTML markup for creating Searchbar
* <input type="search"/>
*
* How to make searchbar in content
* <input type="search" name="" id="" value="" />
*
* How to make searchbar in title
* <div data-role="header" data-position ="fixed" >
* <h1>Searchbar</h1>
* <input type="search" name="" id="" value="" />
* </div>
*
* How to make searchbar inside optionheader
* <div data-role="header" data-position ="fixed" >
* <h1>Searchbar</h1>
* <div id="myoptionheader2" data-role="optionheader">
* <input type="search" name="" id="" value="" />
* </div>
* </div>
*/
(function ( $, undefined ) {
$.widget( "tizen.searchbar", $.mobile.widget, {
options: {
theme: null,
initSelector: "input[type='search'],:jqmData(type='search'), input[type='tizen-search'],:jqmData(type='tizen-search')"
},
_create: function () {
var input = this.element,
o = this.options,
theme = o.theme || $.mobile.getInheritedTheme( this.element, "c" ),
themeclass = " ui-body-" + theme,
focusedEl,
clearbtn,
currentPage = input.closest( ".ui-page" ),
searchicon,
cancelbtn,
defaultText,
defaultTextClass,
trimedText,
newClassName,
newStyle,
newDiv,
inputedText,
extraLineHeight,
keyupTimeoutBuffer,
keyup,
keyupTimeout;
function toggleClear() {
if ( !input.val() ) {
clearbtn.addClass( "ui-input-clear-hidden" );
} else {
clearbtn.removeClass( "ui-input-clear-hidden" );
}
}
function showCancel() {
focusedEl
.addClass( "ui-input-search-default" )
.removeClass( "ui-input-search-wide" );
cancelbtn
.addClass( "ui-btn-cancel-show" )
.removeClass( "ui-btn-cancel-hide" );
searchicon.hide();
}
function hideCancel() {
focusedEl
.addClass( "ui-input-search-wide" )
.removeClass( "ui-input-search-default" );
cancelbtn
.addClass( "ui-btn-cancel-hide" )
.removeClass( "ui-btn-cancel-show" );
if ( input.val() == "" ) {
searchicon.show();
}
toggleClear();
}
$( "label[for='" + input.attr( "id" ) + "']" ).addClass( "ui-input-text" );
focusedEl = input.addClass( "ui-input-text ui-body-" + theme );
// XXX: Temporary workaround for issue 785 (Apple bug 8910589).
// Turn off autocorrect and autocomplete on non-iOS 5 devices
// since the popup they use can't be dismissed by the user. Note
// that we test for the presence of the feature by looking for
// the autocorrect property on the input element. We currently
// have no test for iOS 5 or newer so we're temporarily using
// the touchOverflow support flag for jQM 1.0. Yes, I feel dirty. - jblas
if ( typeof input[0].autocorrect !== "undefined" && !$.support.touchOverflow ) {
// Set the attribute instead of the property just in case there
// is code that attempts to make modifications via HTML.
input[0].setAttribute( "autocorrect", "off" );
input[0].setAttribute( "autocomplete", "off" );
}
focusedEl = input.wrap( "<div class='ui-input-search ui-shadow-inset ui-corner-all ui-btn-shadow" + themeclass + "'></div>" ).parent();
clearbtn = $( "<a href='#' class='ui-input-clear' title='clear text'>clear text</a>" )
.tap( function ( event ) {
event.preventDefault();
event.stopPropagation();
input.val( "" )
.blur()
.focus()
.trigger( "change" )
.trigger( "input" );
clearbtn.addClass( "ui-input-clear-hidden" );
} )
.appendTo( focusedEl )
.buttonMarkup({
icon: "deleteSearch",
iconpos: "notext",
corners: true,
shadow: true
} );
toggleClear();
input.keyup( toggleClear );
input.bind( 'paste cut keyup focus change blur', toggleClear );
//SLP --start search bar with cancel button
focusedEl.wrapAll( "<div class='input-search-bar'></div>" );
input.tap( function ( event ) {
inputedText = input.val();
input
.blur()
.focus();
} );
searchicon = $("<div class='ui-image-search ui-image-searchfield'></div>");
searchicon
.tap( function ( event ) {
searchicon.hide();
input
.blur()
.focus();
} )
.appendTo( focusedEl );
cancelbtn = $( "<a href='#' class='ui-input-cancel' title='clear text'>Cancel</a>" )
.tap(function ( event ) {
event.preventDefault();
event.stopPropagation();
input
.val( "" )
.blur()
.trigger( "change" );
hideCancel();
} )
.appendTo( focusedEl.parent() )
.buttonMarkup( {
iconpos: "cancel",
corners: true,
shadow: true
} );
// Input Focused
input.focus( function () {
showCancel();
focusedEl.addClass( "ui-focus" );
} );
// Input Blured
/* When user touch on page, it's same to blur */
$( "div.input-search-bar" ).tap( function ( event ) {
input.focus();
event.stopPropagation();
} );
$( currentPage ).bind("tap", function ( e ) {
focusedEl.removeClass( "ui-focus" );
hideCancel();
input.trigger( "change" );
} );
// Autogrow
if ( input.is( "textarea" ) ) {
extraLineHeight = 15;
keyupTimeoutBuffer = 100;
keyup = function () {
var scrollHeight = input[ 0 ].scrollHeight,
clientHeight = input[ 0 ].clientHeight;
if ( clientHeight < scrollHeight ) {
input.height(scrollHeight + extraLineHeight);
}
};
input.keyup( function () {
clearTimeout( keyupTimeout );
keyupTimeout = setTimeout( keyup, keyupTimeoutBuffer );
});
// binding to pagechange here ensures that for pages loaded via
// ajax the height is recalculated without user input
$( document ).one( "pagechange", keyup );
// Issue 509: the browser is not providing scrollHeight properly until the styles load
if ( $.trim( input.val() ) ) {
// bind to the window load to make sure the height is calculated based on BOTH
// the DOM and CSS
$( window ).load( keyup );
}
}
// Default Text
defaultText = input.jqmData( "default-text" );
if ( ( defaultText != undefined ) && ( defaultText.length > 0 ) ) {
defaultTextClass = "ui-input-default-text";
trimedText = defaultText.replace(/\s/g, "");
/* Make new class for default text string */
newClassName = defaultTextClass + "-" + trimedText;
newStyle = $( "<style>" + '.' + newClassName + ":after" + "{content:" + "'" + defaultText + "'" + "}" + "</style>" );
$( 'html > head' ).append( newStyle );
/* Make new empty <DIV> for default text */
newDiv = $( "<div></div>" );
/* Add class and append new div */
newDiv.addClass( defaultTextClass );
newDiv.addClass( newClassName );
newDiv.tap( function ( event ) {
input.blur();
input.focus();
} );
input.parent().append( newDiv );
/* When focus, default text will be hide. */
input
.focus( function () {
input.parent().find( "div.ui-input-default-text" ).addClass( "ui-input-default-hidden" );
} )
.blur( function () {
var inputedText = input.val();
if ( inputedText.length > 0 ) {
input.parent().find( "div.ui-input-default-text" ).addClass( "ui-input-default-hidden" );
} else {
input.parent().find( "div.ui-input-default-text" ).removeClass( "ui-input-default-hidden" );
}
} );
}
},
disable: function () {
this.element.attr( "disabled", true );
this.element.parent().addClass( "ui-disabled" );
},
enable: function () {
this.element.attr( "disabled", false );
this.element.parent().removeClass( "ui-disabled" );
}
} );
//auto self-init widgets
$( document ).bind( "pagecreate create", function ( e ) {
$.tizen.searchbar.prototype.enhanceWithin( e.target );
} );
}( jQuery ) );
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
* Copyright (c) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Elliot Smith <elliot.smith@intel.com>
*/
// shortcutscroll is a scrollview controller, which binds
// a scrollview to a a list of short cuts; the shortcuts are built
// from the text on dividers in the list. Clicking on a shortcut
// instantaneously jumps the scrollview to the selected list divider;
// mouse movements on the shortcut column move the scrollview to the
// list divider matching the text currently under the touch; a popup
// with the text currently under the touch is also displayed.
//
// To apply, add the attribute data-shortcutscroll="true" to a listview
// (a <ul> or <ol> element inside a page). Alternatively, call
// shortcutscroll() on an element.
//
// The closest element with class ui-scrollview-clip is used as the
// scrollview to be controlled.
//
// If a listview has no dividers or a single divider, the widget won't
// display.
(function ( $, undefined ) {
$.widget( "tizen.shortcutscroll", $.mobile.widget, {
options: {
initSelector: ":jqmData(shortcutscroll)"
},
_create: function () {
var $el = this.element,
self = this,
$popup,
page = $el.closest( ':jqmData(role="page")' ),
jumpToDivider;
this.scrollview = $el.closest( '.ui-scrollview-clip' );
this.shortcutsContainer = $( '<div class="ui-shortcutscroll"/>' );
this.shortcutsList = $( '<ul></ul>' );
// popup for the hovering character
this.shortcutsContainer.append($( '<div class="ui-shortcutscroll-popup"></div>' ) );
$popup = this.shortcutsContainer.find( '.ui-shortcutscroll-popup' );
this.shortcutsContainer.append( this.shortcutsList );
this.scrollview.append( this.shortcutsContainer );
// find the bottom of the last item in the listview
this.lastListItem = $el.children().last();
// remove scrollbars from scrollview
this.scrollview.find( '.ui-scrollbar' ).hide();
jumpToDivider = function ( divider ) {
// get the vertical position of the divider (so we can scroll to it)
var dividerY = $( divider ).position().top,
// find the bottom of the last list item
bottomOffset = self.lastListItem.outerHeight( true ) + self.lastListItem.position().top,
scrollviewHeight = self.scrollview.height(),
// check that after the candidate scroll, the bottom of the
// last item will still be at the bottom of the scroll view
// and not some way up the page
maxScroll = bottomOffset - scrollviewHeight,
dstOffset;
dividerY = ( dividerY > maxScroll ? maxScroll : dividerY );
// don't apply a negative scroll, as this means the
// divider should already be visible
dividerY = Math.max( dividerY, 0 );
// apply the scroll
self.scrollview.scrollview( 'scrollTo', 0, -dividerY );
dstOffset = self.scrollview.offset();
$popup
.text( $( divider ).text() )
.offset( { left : dstOffset.left + ( self.scrollview.width() - $popup.width() ) / 2,
top : dstOffset.top + ( self.scrollview.height() - $popup.height() ) / 2 } )
.show();
};
this.shortcutsList
// bind mouse over so it moves the scroller to the divider
.bind( 'touchstart mousedown vmousedown touchmove vmousemove vmouseover ', function ( e ) {
// Get coords relative to the element
var coords = $.mobile.tizen.targetRelativeCoordsFromEvent( e ),
shortcutsListOffset = self.shortcutsList.offset();
// If the element is a list item, get coordinates relative to the shortcuts list
if ( e.target.tagName.toLowerCase() === "li" ) {
coords.x += $( e.target ).offset().left - shortcutsListOffset.left;
coords.y += $( e.target ).offset().top - shortcutsListOffset.top;
}
// Hit test each list item
self.shortcutsList.find( 'li' ).each( function () {
var listItem = $( this ),
l = listItem.offset().left - shortcutsListOffset.left,
t = listItem.offset().top - shortcutsListOffset.top,
r = l + Math.abs(listItem.outerWidth( true ) ),
b = t + Math.abs(listItem.outerHeight( true ) );
if ( coords.x >= l && coords.x <= r && coords.y >= t && coords.y <= b ) {
jumpToDivider( $( listItem.data( 'divider' ) ) );
return false;
}
return true;
} );
e.preventDefault();
e.stopPropagation();
} )
// bind mouseout of the shortcutscroll container to remove popup
.bind( 'touchend mouseup vmouseup vmouseout', function () {
$popup.hide();
} );
if ( page && !( page.is( ':visible' ) ) ) {
page.bind( 'pageshow', function () { self.refresh(); } );
} else {
this.refresh();
}
// refresh the list when dividers are filtered out
$el.bind( 'updatelayout', function () {
self.refresh();
} );
},
refresh: function () {
var self = this,
shortcutsTop,
minClipHeight,
dividers,
listItems;
this.shortcutsList.find( 'li' ).remove();
// get all the dividers from the list and turn them into shortcuts
dividers = this.element.find( '.ui-li-divider' );
// get all the list items
listItems = this.element.find( 'li:not(.ui-li-divider)) ');
// only use visible dividers
dividers = dividers.filter( ':visible' );
listItems = listItems.filter( ':visible' );
if ( dividers.length < 2 ) {
this.shortcutsList.hide();
return;
}
this.shortcutsList.show();
this.lastListItem = listItems.last();
dividers.each( function ( index, divider ) {
self.shortcutsList
.append( $( '<li>' + $( divider ).text() + '</li>' )
.data( 'divider', divider ) );
} );
// position the shortcut flush with the top of the first list divider
shortcutsTop = dividers.first().position().top;
this.shortcutsContainer.css( 'top', shortcutsTop );
// make the scrollview clip tall enough to show the whole of the shortcutslist
minClipHeight = shortcutsTop + this.shortcutsContainer.outerHeight() + 'px';
this.scrollview.css( 'min-height', minClipHeight );
}
} );
$( document ).bind( "pagecreate create", function ( e ) {
$( $.tizen.shortcutscroll.prototype.options.initSelector, e.target )
.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
.shortcutscroll();
} );
} ( jQuery ) );
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
* Copyright (c) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Max Waterman <max.waterman@intel.com>
* Authors: Minkyu Kang <mk7.kang@samsung.com>
*/
/**
* tizenslider modifies the JQuery Mobile slider and is created in the same way.
*
* See the JQuery Mobile slider widget for more information :
* http://jquerymobile.com/demos/1.0a4.1/docs/forms/forms-slider.html
*
* The JQuery Mobile slider option:
* theme: specify the theme using the 'data-theme' attribute
*
* Options:
* theme: string; the theme to use if none is specified using the 'data-theme' attribute
* default: 'c'
* popupEnabled: boolean; controls whether the popup is displayed or not
* specify if the popup is enabled using the 'data-popupEnabled' attribute
* set from javascript using .tizenslider('option','popupEnabled',newValue)
*
* Events:
* changed: triggers when the value is changed (rather than when the handle is moved)
*
* Examples:
*
* <a href="#" id="popupEnabler" data-role="button" data-inline="true">Enable popup</a>
* <a href="#" id="popupDisabler" data-role="button" data-inline="true">Disable popup</a>
* <div data-role="fieldcontain">
* <input id="mySlider" data-theme='a' data-popupenabled='false' type="range" name="slider" value="7" min="0" max="9" />
* </div>
* <div data-role="fieldcontain">
* <input id="mySlider2" type="range" name="slider" value="77" min="0" max="777" />
* </div>
*
* // disable popup from javascript
* $('#mySlider').tizenslider('option','popupEnabled',false);
*
* // from buttons
* $('#popupEnabler').bind('vclick', function() {
* $('#mySlider').tizenslider('option','popupEnabled',true);
* });
* $('#popupDisabler').bind('vclick', function() {
* $('#mySlider').tizenslider('option','popupEnabled',false);
* });
*/
(function ($, window, undefined) {
$.widget("tizen.tizenslider", $.mobile.widget, {
options: {
popupEnabled: true
},
popup: null,
handle: null,
handleText: null,
_create: function () {
this.currentValue = null;
this.popupVisible = false;
var self = this,
inputElement = $(this.element),
slider,
showPopup,
hidePopup,
positionPopup,
updateSlider,
slider_bar,
handle_press,
popupEnabledAttr,
icon;
// apply jqm slider
inputElement.slider();
// hide the slider input element proper
inputElement.hide();
self.popup = $('<div class="ui-slider-popup"></div>');
// set the popupEnabled according to the html attribute
popupEnabledAttr = inputElement.attr('data-popupenabled');
if ( popupEnabledAttr !== undefined ) {
self.options.popupEnabled = (popupEnabledAttr === 'true');
}
// get the actual slider added by jqm
slider = inputElement.next('.ui-slider');
icon = inputElement.attr('data-icon');
// wrap the background
if ( icon === undefined ) {
slider.wrap('<div class="ui-slider-bg"></div>');
} else {
slider.wrap('<div class="ui-slider-icon-bg"></div>');
}
// get the handle
self.handle = slider.find('.ui-slider-handle');
// remove the rounded corners from the slider and its children
slider.removeClass('ui-btn-corner-all');
slider.find('*').removeClass('ui-btn-corner-all');
// add icon
switch ( icon ) {
case 'bright':
case 'volume':
slider.before( $('<div class="ui-slider-left-' +
icon + '"></div>') );
slider.after( $('<div class="ui-slider-right-' +
icon + '"></div>') );
break;
case 'text':
slider.before( $('<div class="ui-slider-left-text">' +
'<span style="position:relative;top:0.4em;">' +
inputElement.attr('data-text-left') +
'</span></div>') );
slider.after( $('<div class="ui-slider-right-text">' +
'<span style="position:relative;top:0.4em;">' +
inputElement.attr('data-text-right') +
'</span></div>') );
break;
}
// slider bar
slider.append($('<div class="ui-slider-bar"></div>'));
self.slider_bar = slider.find('.ui-slider-bar');
// handle press
slider.append($('<div class="ui-slider-handle-press"></div>'));
self.handle_press = slider.find('.ui-slider-handle-press');
self.handle_press.css('display', 'none');
// add a popup element (hidden initially)
slider.before(self.popup);
self.popup.hide();
// get the element where value can be displayed
self.handleText = slider.find('.ui-btn-text');
if ( inputElement.attr('max') > 999 ) {
self.handleText.css('font-size', '0.8em');
}
// set initial value
self.updateSlider();
// bind to changes in the slider's value to update handle text
this.element.bind('change', function () {
self.updateSlider();
});
// bind clicks on the handle to show the popup
self.handle.bind('vmousedown', function () {
self.showPopup();
});
// watch events on the document to turn off the slider popup
slider.add(document).bind('vmouseup', function () {
self.hidePopup();
});
},
_handle_press_show: function () {
this.handle_press.css('display', '');
},
_handle_press_hide: function () {
this.handle_press.css('display', 'none');
},
// position the popup
positionPopup: function () {
var dstOffset = this.handle.offset();
this.popup.offset({
left: dstOffset.left + (this.handle.width() - this.popup.width()) / 2,
top: dstOffset.top - this.popup.outerHeight() + 15
});
this.handle_press.offset({
left: dstOffset.left,
top: dstOffset.top
});
},
// show value on the handle and in popup
updateSlider: function () {
if ( this.popupVisible ) {
this.positionPopup();
}
// remove the title attribute from the handle (which is
// responsible for the annoying tooltip); NB we have
// to do it here as the jqm slider sets it every time
// the slider's value changes :(
this.handle.removeAttr('title');
this.slider_bar.width(this.handle.css('left'));
var newValue = this.element.val();
if ( newValue === this.currentValue ) {
return;
}
this.currentValue = newValue;
this.handleText.text(newValue);
this.popup.html(newValue);
this.element.trigger('update', newValue);
},
// show the popup
showPopup: function () {
if ( !(this.options.popupEnabled && !this.popupVisible) ) {
return;
}
this.handleText.hide();
this.popup.show();
this.popupVisible = true;
this._handle_press_show();
},
// hide the popup
hidePopup: function () {
if ( !(this.options.popupEnabled && this.popupVisible) ) {
return;
}
this.handleText.show();
this.popup.hide();
this.popupVisible = false;
this._handle_press_hide();
},
_setOption: function (key, value) {
var needToChange = ( value !== this.options[key] );
if ( !needToChange ) {
return;
}
switch ( key ) {
case 'popupEnabled':
this.options.popupEnabled = value;
if ( this.options.popupEnabled ) {
this.updateSlider();
} else {
this.hidePopup();
}
break;
}
}
});
// stop jqm from initialising sliders
$(document).bind("pagebeforecreate", function ( e ) {
if ($.data(window, "jqmSliderInitSelector") === undefined ) {
$.data(window, "jqmSliderInitSelector",
$.mobile.slider.prototype.options.initSelector);
$.mobile.slider.prototype.options.initSelector = null;
}
});
// initialise sliders with our own slider
$(document).bind("pagecreate", function ( e ) {
var jqmSliderInitSelector = $.data(window, "jqmSliderInitSelector");
$(e.target).find(jqmSliderInitSelector).not('select').tizenslider();
$(e.target).find(jqmSliderInitSelector).filter('select').slider();
});
}( jQuery, this ));
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
* Copyright (c) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Kalyan Kondapally <kalyan.kondapally@intel.com>,
* Elliot Smith <elliot.smith@intel.com>
*/
// Widget which turns a list into a "swipe list":
// i.e. each list item has a sliding "cover" which can be swiped
// to the right (to reveal buttons underneath) or left (to
// cover the buttons again). Clicking on a button under a swipelist
// also moves the cover back to the left.
//
// To create a swipelist, you need markup like this:
//
// <pre>
// &lt;ul data-role="swipelist"&gt;<br/>
// &lt;li&gt;<br/>
// &lt;div class="ui-grid-b"&gt;<br/>
// &lt;div class="ui-block-a"&gt;<br/>
// &lt;a href="#" data-role="button" data-theme="a"&gt;Twitter&lt;/a&gt;<br/>
// &lt;/div&gt;<br/>
// &lt;div class="ui-block-b"&gt;<br/>
// &lt;a href="#" data-role="button" data-theme="b"&gt;FaceBook&lt;/a&gt;<br/>
// &lt;/div&gt;<br/>
// &lt;div class="ui-block-c"&gt;<br/>
// &lt;a href="#" data-role="button" data-theme="c"&gt;Google+&lt;/a&gt;<br/>
// &lt;/div&gt;<br/>
// &lt;/div&gt;<br/>
// &lt;div data-role="swipelist-item-cover"&gt;Nigel&lt;/div&gt;<br/>
// &lt;/li&gt;<br/>
// ...<br/>
// &lt;/ul&gt;
// </pre>
//
// In this case, the cover is over a grid of buttons;
// but it is should also be possible to use other types of markup under the
// list items.
//
// Note the use of a separate div, parented by the li element, marked
// up with data-role="swipelist-item-cover". This div will usually
// contain text. If you want other elements in your swipelist covers,
// you may need to style them yourself. Because the covers aren't
// technically list items, you may need to do some work to make them
// look right.
//
// WARNING: This doesn't work well inside a scrollview widget, as
// the touch events currently interfere with each other badly (e.g.
// a swipe will work but cause a scroll as well).
//
// Theme: default is to use the theme on the target element,
// theme passed in options, parent theme, or 'c' if none of the above.
// If list items are themed individually, the cover will pick up the
// theme of the list item which is its parent.
//
// Events:
//
// animationComplete: Triggered by a cover when it finishes sliding
// (to either the right or left).
(function ($) {
$.widget("tizen.swipelist", $.mobile.widget, {
options: {
theme: null
},
_create: function () {
// use the theme set on the element, set in options,
// the parent theme, or 'c' (in that order of preference)
var theme = this.element.jqmData('theme') ||
this.options.theme ||
this.element.parent().jqmData('theme') ||
'c';
this.options.theme = theme;
this.refresh();
},
refresh: function () {
this._cleanupDom();
var self = this,
defaultCoverTheme,
covers;
defaultCoverTheme = 'ui-body-' + this.options.theme;
// swipelist is a listview
if (!this.element.hasClass('ui-listview')) {
this.element.listview();
}
this.element.addClass('ui-swipelist');
// get the list item covers
covers = this.element.find(':jqmData(role="swipelist-item-cover")');
covers.each(function () {
var cover = $(this),
coverTheme = defaultCoverTheme,
// get the parent li element and add classes
item = cover.closest('li'),
itemHasThemeClass;
// add swipelist CSS classes
item.addClass('ui-swipelist-item');
cover.addClass('ui-swipelist-item-cover');
// set swatch on cover: if the nearest list item has
// a swatch set on it, that will be used; otherwise, use
// the swatch set for the swipelist
itemHasThemeClass = item.attr('class')
.match(/ui\-body\-[a-z]|ui\-bar\-[a-z]/);
if (itemHasThemeClass) {
coverTheme = itemHasThemeClass[0];
}
cover.addClass(coverTheme);
// wrap inner HTML (so it can potentially be styled)
if (cover.has('.ui-swipelist-item-cover-inner').length === 0) {
cover.wrapInner($('<span/>').addClass('ui-swipelist-item-cover-inner'));
}
// bind to swipe events on the cover and the item
if (!(cover.data('animateRight') && cover.data('animateLeft'))) {
cover.data('animateRight', function () {
self._animateCover(cover, 100);
});
cover.data('animateLeft', function () {
self._animateCover(cover, 0);
});
}
// bind to synthetic events
item.bind('swipeleft', cover.data('animateLeft'));
cover.bind('swiperight', cover.data('animateRight'));
// any clicks on buttons inside the item also trigger
// the cover to slide back to the left
item.find('.ui-btn').bind('vclick', cover.data('animateLeft'));
});
},
_cleanupDom: function () {
var self = this,
defaultCoverTheme,
covers;
defaultCoverTheme = 'ui-body-' + this.options.theme;
this.element.removeClass('ui-swipelist');
// get the list item covers
covers = this.element.find(':jqmData(role="swipelist-item-cover")');
covers.each(function () {
var cover = $(this),
coverTheme = defaultCoverTheme,
text,
wrapper,
// get the parent li element and add classes
item = cover.closest('li'),
itemClass,
itemHasThemeClass;
// remove swipelist CSS classes
item.removeClass('ui-swipelist-item');
cover.removeClass('ui-swipelist-item-cover');
// remove swatch from cover: if the nearest list item has
// a swatch set on it, that will be used; otherwise, use
// the swatch set for the swipelist
itemClass = item.attr('class');
itemHasThemeClass = itemClass &&
itemClass.match(/ui\-body\-[a-z]|ui\-bar\-[a-z]/);
if (itemHasThemeClass) {
coverTheme = itemHasThemeClass[0];
}
cover.removeClass(coverTheme);
// remove wrapper HTML
wrapper = cover.find('.ui-swipelist-item-cover-inner');
wrapper.children().unwrap();
text = wrapper.text();
if (text) {
cover.append(text);
wrapper.remove();
}
// unbind swipe events
if (cover.data('animateRight') && cover.data('animateLeft')) {
cover.unbind('swiperight', cover.data('animateRight'));
item.unbind('swipeleft', cover.data('animateLeft'));
// unbind clicks on buttons inside the item
item.find('.ui-btn').unbind('vclick', cover.data('animateLeft'));
cover.data('animateRight', null);
cover.data('animateLeft', null);
}
});
},
// NB I tried to use CSS animations for this, but the performance
// and appearance was terrible on Android 2.2 browser;
// so I reverted to jQuery animations
//
// once the cover animation is done, the cover emits an
// animationComplete event
_animateCover: function (cover, leftPercentage) {
var animationOptions = {
easing: 'linear',
duration: 'fast',
queue: true,
complete: function () {
cover.trigger('animationComplete');
}
};
cover.stop();
cover.clearQueue();
cover.animate({left: leftPercentage + '%'}, animationOptions);
},
destroy: function () {
this._cleanupDom();
}
});
$(document).bind("pagecreate", function (e) {
$(e.target).find(":jqmData(role='swipelist')").swipelist();
});
}(jQuery));
/*
* jQuery Mobile Widget @VERSION
*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
* Copyright (c) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software" ),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Authors: Gabriel Schulhof <gabriel.schulhof@intel.com>
*/
// Displays a simple two-state switch.
//
// To apply, add the attribute data-role="switch" to a <div>
// element inside a page. Alternatively, call switch()
// on an element, like this :
//
// $( "#myswitch" ).toggleswitch();
// where the html might be :
// <div id="myswitch"></div>
//
// Options:
// checked: Boolean; the state of the switch
// Default: true (up)
//
// Events:
// changed: Emitted when the switch is changed
(function ( $, undefined ) {
$.widget( "tizen.toggleswitch", $.tizen.widgetex, {
options: {
onText : "On",
offText : "Off",
checked : true,
initSelector : ":jqmData(role='toggleswitch')"
},
_htmlProto: {
source:
$("<div><div id='outer' class='ui-btn ui-btn-corner-all ui-btn-inline ui-shadow ui-toggleswitch'>" +
" <div class='ui-btn ui-btn-corner-all ui-btn-up-c toggleswitch-background'></div>" +
" <div class='ui-btn ui-btn-corner-all ui-btn-up-c toggleswitch-background ui-btn-active' id='bg'></div>" +
" <a data-role='button' data-shadow='false' class='toggleswitch-floating-button toggleswitch-mover' id='normal'>" +
" <span data-normal-text='true'></span>" +
" </a>" +
" <a data-role='button' data-shadow='false' class='toggleswitch-floating-button toggleswitch-mover ui-btn-active' id='active'>" +
" <span data-active-text='true'></span>" +
" </a>" +
" <a data-role='button' data-shadow='false' class='toggleswitch-sizer'>" +
" <span data-normal-text='true'></span>" +
" </a>" +
" <a data-role='button' data-shadow='false' class='toggleswitch-sizer'>" +
" <span data-active-text='true'></span>" +
" </a>" +
" <a data-role='button' data-shadow='false' class='toggleswitch-floating-button' id='button'>" +
" <span id='btn-span'></span>" +
" </a>" +
"</div>" +
"</div>")
, ui: {
outer : "#outer",
bg : "#bg",
txtMovers : {
normal : "#normal",
active : "#active"
},
btn : "#button",
btnSpan : "#btn-span",
txt : {
normal : "[data-normal-text]",
active : "[data-active-text]"
}
}
},
_value: {
attr: "data-" + ( $.mobile.ns || "" ) + "checked",
signal: "changed"
},
_create: function () {
var self = this;
this.element
.css( "display", "none" )
.after( this._ui.outer );
this._ui.outer.find( "a" ).buttonMarkup();
this._ui.txtMovers.normal
.add( this._ui.txtMovers.active )
.find( "*" )
.css( { "border-color": "transparent" } );
this._ui.btn.addClass( "toggleswitch-button" );
/*
// Crutches for IE: It does not seem to understand opacity specified in a class, nor that opacity of an element
// affects all its children
if ($.mobile.browser.ie) {
// Remove this class, because it has no effect in IE :-S
this._ui.outer.find( "*" ).removeClass( "toggleswitch-button-transparent" );
// After adding the button markup, make everything transparent
this._ui.normalBackground.find( "*" ).css( "opacity", 0.0);
this._ui.activeBackground.find( "*" ).css( "opacity", 0.0);
this._ui.refButton.add( this._ui.refButton.find( "*" )).css( "opacity", 0.0);
this._ui.realButton.add( this._ui.realButton.find( "*" )).css( "opacity", 0.0);
// ... except the buttons that display the inital position of the switch
this._ui.initButtons
.add( this._ui.initButtons.find( "*" ))
.add( this._ui.fButton.find( "*" ))
.add( this._ui.fButton)
.css( "opacity", 1.0);
}
*/
$.extend( this, {
_initial: true
} );
this._ui.btn
.add( this._ui.outer )
.bind( "vclick", function ( e ) {
self._setChecked( !( self.options.checked ) );
e.stopPropagation();
} );
},
/*
_makeTransparent: function (obj, b) {
if ($.mobile.browser.ie)
obj.add(obj.find( "*" )).css( "opacity", b ? 0.0 : 1.0);
else
obj[b ? "addClass" : "removeClass"]( "toggleswitch-button-transparent" );
},
*/
_setDisabled: function ( value ) {
$.tizen.widgetex.prototype._setDisabled.call( this, value );
this._ui.outer[value ? "addClass" : "removeClass"]( "ui-disabled" );
},
_updateBtnText: function () {
var noText = ( ( ( this.options.offText || "" ) === "" &&
( this.options.onText || "" ) === "" ) );
this._ui.btnSpan.html( ( noText ? "" : "&nbsp;" ) );
this._ui.outer.find( "a" )[( noText ? "addClass" : "removeClass" )]( "ui-btn-icon-notext" );
},
_setOnText: function ( value ) {
this._ui.txt.active.text( value );
this.options.onText = value;
this.element.attr( "data-" + ( $.mobile.ns || "" ) + "on-text", value );
this._updateBtnText();
},
_setOffText: function ( value ) {
this._ui.txt.normal.text( value );
this.options.offText = value;
this.element.attr( "data-" + ($.mobile.ns || "" ) + "off-text", value );
this._updateBtnText();
},
_setChecked: function ( checked ) {
if ( this.options.checked != checked ) {
var dst = checked
? { bg: "0%", normalTop: "-50%", activeBot: "0%" }
: { bg: "50%", normalTop: "0%", activeBot: "-50%" },
method = ( this._initial ? "css" : "animate" );
this._ui.btn.add( this._ui.bg )[method]( { top: dst.bg } );
this._ui.txtMovers.normal[method]( { top: dst.normalTop } );
this._ui.txtMovers.active[method]( { bottom: dst.activeBot } );
this._initial = false;
this.options.checked = checked;
this.element.attr( "data-" + ( $.mobile.ns || "" ) + "checked", checked );
this._setValue( checked );
}
}
} );
$( document ).bind( "pagecreate create", function ( e ) {
$( $.tizen.toggleswitch.prototype.options.initSelector, e.target )
.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
.toggleswitch();
} );
}( jQuery ) );
/*
* This software is licensed under the MIT licence (as defined by the OSI at
* http://www.opensource.org/licenses/mit-license.php)
*
* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
* Copyright (c) 2011 by Intel Corporation Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*/
( function ($, undefined) {
$.widget( "tizen.triangle", $.tizen.widgetex, {
options: {
extraClass: "",
offset: null,
color: null,
location: "top",
initSelector: ":jqmData(role='triangle')"
},
_create: function () {
var triangle = $( "<div></div>", {"class" : "ui-triangle"} );
$.extend(this, {
_triangle: triangle
});
this.element.addClass( "ui-triangle-container" ).append( triangle );
},
_doCSS: function () {
var location = ( this.options.location || "top" ),
offsetCoord = ( ($.inArray(location, ["top", "bottom"]) === -1) ? "top" : "left"),
cssArg = {
"border-bottom-color" : "top" === location ? this.options.color : "transparent",
"border-top-color" : "bottom" === location ? this.options.color : "transparent",
"border-left-color" : "right" === location ? this.options.color : "transparent",
"border-right-color" : "left" === location ? this.options.color : "transparent"
};
cssArg[offsetCoord] = this.options.offset;
this._triangle.removeAttr( "style" ).css( cssArg );
},
_setOffset: function ( value ) {
this.options.offset = value;
this.element.attr( "data-" + ($.mobile.ns || "") + "offset", value );
this._doCSS();
},
_setExtraClass: function ( value ) {
this._triangle.addClass( value );
this.options.extraClass = value;
this.element.attr( "data-" + ($.mobile.ns || "") + "extra-class", value );
},
_setColor: function ( value ) {
this.options.color = value;
this.element.attr( "data-" + ($.mobile.ns || "") + "color", value );
this._doCSS();
},
_setLocation: function ( value ) {
this.element
.removeClass( "ui-triangle-container-" + this.options.location )
.addClass( "ui-triangle-container-" + value );
this._triangle
.removeClass( "ui-triangle-" + this.options.location )
.addClass( "ui-triangle-" + value );
this.options.location = value;
this.element.attr( "data-" + ($.mobile.ns || "") + "location", value );
this._doCSS();
}
});
$( document ).bind( "pagecreate create", function ( e ) {
$($.tizen.triangle.prototype.options.initSelector, e.target)
.not(":jqmData(role='none'), :jqmData(role='nojs')")
.triangle();
});
}(jQuery) );
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Author: Kangsik Kim <kangsik81.kim@samsung.com>
*/
/**
* Virtual Grid Widget for unlimited data.
* To support more then 1,000 items, special grid widget developed.
* Fast initialize and light DOM tree.
*
* HTML Attributes:
*
* data-role: virtualgridview
* data-template : jQuery.template ID that populate into virtual list
* data-dbtable : DB Table name. It used as window[DB NAME]. Loaded data should be converted as window object.
* data-dbkey : Unique key of DB Table. To sync each element on virtual list with DB table.
* data-column : Set a number of column. (Default : 3)
* data-row : Set a number of row. (Default : 10)
*
* ID : <UL> element that has "data-role=virtualgrid" must have ID attribute.
* Class : <UL> element that has "data-role=virtualgrid" should have "vgLoadSuccess" class to guaranty DB loading is completed.
*
* APIs:
*
* create ( void )
* : API to call _create method. API for AJAX or DB loading callback.
*
* Events:
*
*
* Examples:
*
* <script id="tizen-demo-namecard" type="text/x-jquery-tmpl">
* <div class="ui-demo-namecard">
* <div class="ui-demo-namecard-pic">
* <img class="ui-demo-namecard-pic-img" src="${TEAM_LOGO}" />
* </div>
* <div class="ui-demo-namecard-contents">
* <span class="name ui-li-text-main">${NAME}</span>
* <span class="active ui-li-text-sub">${ACTIVE}</span>
* <span class="from ui-li-text-sub">${FROM}</span>
* </div>
* </div>
* </script>
* <div id="virtualgrid-demo" data-role="virtualgrid" data-column="3" data-row="60" data-template="tizen-demo-namecard" data-dbtable="JSON_DATA" >
* </div>
*
*/
( function ( $, window, undefined ) {
$.widget( "tizen.virtualgrid", $.mobile.widget, {
options : {
id : "",
column : 3,
dbtable : "",
template : "",
row : 20,
dbkey : false
},
create : function () {
this._create();
},
_create : function () {
$.extend( this, {
NO_SCROLL : 0,
SCROLL_DOWN : 1,
SCROLL_UP : -1,
_titleHeight : 0,
_blockHeight : 0,
_bufferSize : 0,
_columnWidth : 0,
_totalItemCnt : 0,
_totalRowCnt : 0,
_currentIndex : 0,
_remainCount : 0,
_viewHeight : 0,
_direction : 0,
_firstIndex : 0,
_lastIndex : 0,
_prevPos : 0,
_numTopItems : 0
});
var opts = this.options, widget = this;
opts.id = "#" + this.element.attr( 'id' );
if ( $( opts.id ).hasClass( "vgLoadSuccess" ) ) {
$( opts.id ).empty();
// validation row, column count
// initialize global value.
widget._lastIndex = opts.row;
widget._bufferSize = ( parseInt( ( opts.row / 4 ), 10 ) );
widget._totalItemCnt = $( window[opts.dbtable] ).size();
widget._pushData( ( opts.template ), window[opts.dbtable] );
widget._reposition();
widget._addEvents();
}
},
_pushData : function ( template, data ) {
var widget = this,
opts = this.options,
dataTable = data,
myTemplate = $( "#" + template ),
viewcount = opts.row * opts.column,
lastIndex = viewcount,
index = 0,
rowIndex = 0,
colIndex = 0,
wrapBlock = null;
for ( rowIndex = 0; rowIndex < opts.row; rowIndex += 1 ) {
wrapBlock = widget._makeWrapBlock( myTemplate, dataTable );
$( wrapBlock ).attr( "id", "block_" + rowIndex );
$( opts.id ).append( wrapBlock );
}
widget._blockHeight = $( wrapBlock ).outerHeight();
},
// make a single row block
_makeWrapBlock : function ( myTemplate, dataTable ) {
var widget = this,
opts = widget.options,
index = widget._currentIndex,
htmlData = null,
colIndex = 0,
wrapBlock = document.createElement( "div" );
$( wrapBlock ).addClass( "ui-virtualgrid-wrapblock" );
for ( colIndex = 0; colIndex < opts.column; colIndex++ ) {
htmlData = myTemplate.tmpl( dataTable[index] );
$( wrapBlock ).append( htmlData );
index = index <= widget._totalItemCnt ? index + 1 : 0;
}
widget._currentIndex = index;
return wrapBlock;
},
_reposition : function () {
var widget = this,
$view = widget.element,
opts = this.options,
wrapsBlocks = null,
childBlocks = null,
blockCount = 0,
index = 0,
subIndex = 0,
firstBlock = $( ".ui-virtualgrid-wrapblock:first" ),
subBlocks = firstBlock.children();
widget._blockHeight = firstBlock.outerHeight();
widget._titleHeight = firstBlock.position().top;
if ( subBlocks[0] ) {
widget._columnWidth = $( subBlocks[0] ).outerWidth();
}
wrapsBlocks = $( ".ui-virtualgrid-wrapblock" );
blockCount = wrapsBlocks.length;
for ( index = 0; index < blockCount; index += 1 ) {
$( wrapsBlocks[index] ).css( "top", widget._titleHeight + ( index * widget._blockHeight ) );
childBlocks = $( wrapsBlocks[index] ).children();
for ( subIndex = 0; subIndex < childBlocks.length; subIndex += 1 ) {
$( childBlocks[subIndex] ).css( "left", ( subIndex * widget._columnWidth ) + 'px' );
}
}
// check total row count and setup total height
widget._totalRowCnt = ( widget._totalItemCnt % opts.column ) === 0 ? ( widget._totalItemCnt / opts.column ) : ( parseInt( ( widget._totalItemCnt / opts.column ), 10 ) + 1 );
$( opts.id ).height( widget._totalRowCnt * widget._blockHeight );
},
_addEvents : function () {
var widget = this;
$( document ).bind( "scrollupdate.virtualgrid", function ( event ) {
widget._doScrollEvent(event);
});
$( document ).bind( "scrollstop.virtualgrid", function ( event ) {
widget._doScrollEvent(event);
});
},
_doScrollEvent : function ( event ) {
var widget = this,
$view = this.element,
opts = widget.options,
dataList = window [opts.dbtable],
filterCondition = 0,
replaceRowCnt = 0,
replacedCount = 0,
$scrollview = $view.closest (".ui-scrollview-view"),
transformValue = null,
curWindowTop = 0;
transformValue = widget._matrixToArray ($scrollview.css ("-webkit-transform"));
curWindowTop = Math.abs (transformValue [5]);
if (widget._prevPos > curWindowTop) {
widget._direction = widget.SCROLL_UP;
} else if (widget._prevPos < curWindowTop) {
widget._direction = widget.SCROLL_DOWN;
}
if (widget._direction == widget.SCROLL_DOWN) {
filterCondition = (curWindowTop - widget._blockHeight );
replaceRowCnt = $ (".ui-virtualgrid-wrapblock").filter (function () {
return (parseInt (($ (this).position ().top ), 10) < filterCondition );
}).size ();
if (replaceRowCnt > widget._bufferSize) {
$ (document).bind ("touchstart.virtualgrid", function (event) {
event.preventDefault ();
});
replaceRowCnt = replaceRowCnt - widget._bufferSize;
replacedCount = widget._moveTopBottom (widget._firstIndex, widget._lastIndex, replaceRowCnt, opts.dbkey);
widget._firstIndex += replacedCount;
widget._lastIndex += replacedCount;
widget._numTopItems -= replacedCount;
$ (document).unbind ("touchstart.virtualgrid");
}
} else if (widget._direction == widget.SCROLL_UP) {
filterCondition = (curWindowTop + widget._viewHeight + ( widget._blockHeight * 3) );
replaceRowCnt = $ (".ui-virtualgrid-wrapblock").filter (function () {
return (parseInt (($ (this).position ().top ), 10) > filterCondition );
}).size ();
if (replaceRowCnt > widget._bufferSize) {
$ (document).bind ("touchstart.virtualgrid", function (event) {
event.preventDefault ();
});
replaceRowCnt = replaceRowCnt - widget._bufferSize;
replacedCount = widget._moveBottomTop (widget._firstIndex, widget._lastIndex, replaceRowCnt, opts.dbkey);
widget._firstIndex -= replacedCount;
widget._lastIndex -= replacedCount;
widget._numTopItems += replacedCount;
$ (document).unbind ("touchstart.virtualgrid");
}
}
// save preve position information.
widget._prevPos = curWindowTop;
},
/* Matrix to Array function written by Blender@stackoverflow.nnikishi@emich.edu*/
_matrixToArray : function ( matrix ) {
var contents = matrix.substr( 7 );
contents = contents.substr( 0, contents.length - 1 );
return contents.split( ', ' );
},
//Move older item to bottom
_moveTopBottom : function ( v_firstIndex, v_lastIndex, num, key ) {
if ( v_firstIndex < 0 ) {
return;
}
if ( num < 1 ) {
return;
}
var widget = this,
opts = widget.options,
dataList = window[opts.dbtable],
dataIndex = ( ( v_lastIndex ) * opts.column ),
count = 0,
curBlock = null,
cur_item = null,
myTemplate = null,
htmlData = null,
i = 0,
j = 0,
contentsBlocks = null;
// wrap block count
// print argument value
for ( i = 0; i < num; i += 1 ) {
if ( v_lastIndex >= widget._totalRowCnt ) {
break;
}
// select block
curBlock = $( "#block_" + ( v_firstIndex + i ) );
if ( !curBlock ) {
break;
}
contentsBlocks = curBlock.children();
for ( j = 0; j < opts.column; j += 1 ) {
cur_item = contentsBlocks[j];
myTemplate = $( "#" + opts.template );
htmlData = myTemplate.tmpl( dataList[dataIndex] );
widget._replace( cur_item, htmlData, key );
dataIndex += 1;
}
curBlock.css( "top", widget._titleHeight + widget._blockHeight * ( ( v_lastIndex ) ) ).css( "left", 0 );
contentsBlocks.css( "top", widget._titleHeight + widget._blockHeight * ( ( v_lastIndex ) ) );
curBlock.attr( "id", "block_" + ( v_lastIndex ) );
v_lastIndex++;
count++;
}
return count;
},
_moveBottomTop : function ( v_firstIndex, v_lastIndex, num, key ) {
if ( v_firstIndex < 0 ) {
return;
}
if ( num < 1 ) {
return;
}
var widget = this,
opts = widget.options,
dataList = window[opts.dbtable],
dataIndex = ( ( v_firstIndex - 1 ) * opts.column ),
targetBlock = $( ".ui-virtualgrid-wrapblock:first" ),
curBlock = null,
contentsBlocks = null,
cur_item = null,
myTemplate = null,
htmlData = null,
i = 0,
j = 0,
count = 0;
// print argument value
for ( i = 0; i < num; i += 1 ) {
if ( v_firstIndex - 1 < 0 ) {
break;
}
// select block
curBlock = $( "#block_" + ( ( v_lastIndex - 1 ) - i ) );
if ( !curBlock ) {
break;
}
dataIndex = ( ( v_firstIndex - 1 ) * opts.column );
contentsBlocks = curBlock.children();
for ( j = 0; j < opts.column; j += 1 ) {
cur_item = contentsBlocks[j];
myTemplate = $( "#" + opts.template );
htmlData = myTemplate.tmpl( dataList[dataIndex] );
widget._replace( cur_item, htmlData, key );
dataIndex++;
}
curBlock.css( "top", widget._titleHeight + widget._blockHeight * ( ( v_firstIndex - 1 ) ) ).css( "left", 0 );
curBlock.attr( "id", "block_" + ( v_firstIndex - 1 ) );
contentsBlocks.css( "top", widget._titleHeight + widget._blockHeight * ( ( v_firstIndex - 1 ) ) );
v_firstIndex -= 1;
count++;
}
return count;
},
/* Text & image src replace function */
// @param oldItem : prev HtmlDivElement
// @param newItem : new HtmlDivElement for replace
// @param key :
_replace : function ( oldItem, newItem, key ) {
$( oldItem ).find( ".ui-li-text-main", ".ui-li-text-sub", "ui-btn-text" ).each( function ( index ) {
var oldObj = $( this ),
newText = $( newItem ).find( ".ui-li-text-main", ".ui-li-text-sub", "ui-btn-text" ).eq( index ).text();
$( oldObj ).contents().filter( function () {
return ( this.nodeType == 3 );
}).get( 0 ).data = newText;
});
$( oldItem ).find( "img" ).each( function ( imgIndex ) {
var oldObj = $( this ),
newImg = $( newItem ).find( "img" ).eq( imgIndex ).attr( "src" );
$( oldObj ).attr( "src", newImg );
});
if ( key ) {
$( oldItem ).data( key, $( newItem ).data( key ) );
}
}
});
$( document ).bind( "pagecreate create", function () {
$( ":jqmData(role='virtualgrid')" ).virtualgrid();
});
} ( jQuery, window ) );
/* ***************************************************************************
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* ***************************************************************************
*
* Author: Wongi Lee <wongi11.lee@samsung.com>
*/
/**
* Virtual List Widget for unlimited data.
* To support more then 1,000 items, special list widget developed.
* Fast initialize and light DOM tree.
* DB connection and works like DB cursor.
*
* HTML Attributes:
*
* data-role: virtuallistview
* data-template : jQuery.template ID that populate into virtual list
* data-dbtable : DB Table name. It used as window[DB NAME]. Loaded data should be converted as window object.
* data-dbkey : Unique key of DB Table. To sync each element on virtual list with DB table.
* data-row : Optional. Set number of <li> elements that are used for data handling.
*
* ID : <UL> element that has "data-role=virtuallist" must have ID attribute.
* Class : <UL> element that has "data-role=virtuallist" should have "vlLoadSuccess" class to guaranty DB loading is completed.
*
* * APIs:
*
* create ( void )
* : API to call _create method. API for AJAX or DB loading callback.
*
* recreate ( Array )
* : Update virtual list with new data array. For example, update with search result.
*
* Events:
*
* touchstart : Temporary preventDefault applied on touchstart event to avoid broken screen.
*
* Examples:
*
* <script id="tmp-3-2-7" type="text/x-jquery-tmpl">
* <li class="ui-li-3-2-7">
* <span class="ui-li-text-main">${NAME}</span>
* <img src="00_winset_icon_favorite_on.png" class="ui-li-icon-sub">
* <span class="ui-li-text-sub">${ACTIVE}</span>
* <span class="ui-li-text-sub2">${FROM}</span>
* </li>
* </script>
*
* <ul id="virtuallist-normal_3_2_7_ul" data-role="virtuallistview" data-template="tmp-3-2-7" data-dbtable="JSON_DATA" data-row="100">
* </ul>
*
*/
(function ( $, undefined ) {
/* Code for Virtual List Demo */
var listCountPerPage = {}, /* Keeps track of the number of lists per page UID. This allows support for multiple nested list in the same page. https://github.com/jquery/jquery-mobile/issues/1617 */
TOTAL_ITEMS = 0,
LINE_H = 0,
TITLE_H = 0,
CONTAINER_W = 0,
NO_SCROLL = 0, /* ENUM */
SCROLL_DOWN = 1, /* ENUM */
SCROLL_UP = -1, /* ENUM */
MINIMUM_ROW = 20,
direction = NO_SCROLL,
first_index,
last_index,
num_top_items = 0; //By scroll move, number of hidden elements.
$.widget( "tizen.virtuallistview", $.mobile.widget, {
options: {
theme: "s",
countTheme: "c",
headerTheme: "b",
dividerTheme: "b",
splitIcon: "arrow-r",
splitTheme: "b",
inset: false,
id: "", /* Virtual list UL elemet's ID */
childSelector: " li", /* To support swipe list */
dbtable: "",
template : "",
dbkey: false, /* Data's unique Key */
scrollview: false,
row: 100,
page_buf: 50,
initSelector: ":jqmData(role='virtuallistview')"
},
_stylerMouseUp: function () {
$( this ).addClass( "ui-btn-up-s" );
$( this ).removeClass( "ui-btn-down-s" );
},
_stylerMouseDown: function () {
$( this ).addClass( "ui-btn-down-s" );
$( this ).removeClass( "ui-btn-up-s" );
},
_stylerMouseOver: function () {
$( this ).toggleClass( "ui-btn-hover-s" );
},
_stylerMouseOut: function () {
$( this ).toggleClass( "ui-btn-hover-s" );
},
_pushData: function ( template, data ) {
var o = this.options,
i,
dataTable = data,
myTemplate = $( "#" + template ),
lastIndex = ( o.row > data.length ? data.length : o.row ),
htmlData;
for ( i = 0; i < lastIndex; i++ ) {
htmlData = myTemplate.tmpl( dataTable[i] );
$( o.id ).append( $( htmlData ).attr( 'id', 'li_' + i ) );
}
/* After push data, re-style virtuallist widget */
$( o.id ).trigger( "create" );
},
_reposition: function ( event ) {
var o,
t = this,
padding;
if ( event.data ) {
o = event.data;
} else {
o = event;
}
if ( $( o.id + o.childSelector ).size() > 0 ) {
TITLE_H = $( o.id + o.childSelector + ':first' ).position().top;
LINE_H = $( o.id + o.childSelector + ':first' ).outerHeight();
CONTAINER_W = $( o.id ).innerWidth();
padding = parseInt( $( o.id + o.childSelector ).css( "padding-left" ), 10 ) + parseInt( $( o.id + o.childSelector ).css( "padding-right" ), 10 );
/* Add style */
$( o.id + ">" + o.childSelector ).addClass( "position_absolute" ).addClass( "ui-btn-up-s" )
.bind( "mouseup", t._stylerMouseUp )
.bind( "mousedown", t._stylerMouseDown )
.bind( "mouseover", t._stylerMouseOver )
.bind( "mouseout", t._stylerMouseOut );
}
$( o.id + ">" + o.childSelector ).each( function ( index ) {
$( this ).css( "top", TITLE_H + LINE_H * index + 'px' )
.css( "width", CONTAINER_W - padding );
} );
/* Set Max List Height */
$( o.id ).height( TOTAL_ITEMS * LINE_H );
},
_resize: function ( event ) {
var o,
t = this,
padding;
if ( event.data ) {
o = event.data;
} else {
o = event;
}
CONTAINER_W = $( o.id ).innerWidth();
padding = parseInt( $( o.id + o.childSelector ).css( "padding-left" ), 10 ) + parseInt( $( o.id + o.childSelector ).css( "padding-right" ), 10 );
$( o.id + o.childSelector ).each( function (index) {
$( this ).css( "width", CONTAINER_W - padding );
} );
},
_scrollmove: function ( event ) {
var velocity = 0,
o = event.data,
i,
dataList = window[o.dbtable],
_replace, /* Function */
_moveTopBottom, /* Function */
_moveBottomTop, /* Function */
_matrixToArray, /* Function */
$el,
transformValue,
curWindowTop,
cur_num_top_itmes;
/* Text & image src replace function */
_replace = function ( oldItem, newItem, key ) {
var oldObj,
newText,
newImg;
$( oldItem ).find( ".ui-li-text-main", ".ui-li-text-sub", "ui-btn-text" ).each( function ( index ) {
oldObj = $( this );
newText = $( newItem ).find( ".ui-li-text-main", ".ui-li-text-sub", "ui-btn-text" ).eq( index ).text();
$( oldObj).contents().filter( function () {
return ( this.nodeType == 3 );
} ).get( 0 ).data = newText;
} );
$( oldItem ).find( "img" ).each( function ( imgIndex ) {
oldObj = $( this );
newImg = $( newItem ).find( "img" ).eq( imgIndex ).attr( "src" );
$( oldObj ).attr( "src", newImg );
} );
if (key) {
$( oldItem ).data( key, $( newItem ).data( key ) );
}
};
//Move older item to bottom
_moveTopBottom = function ( v_firstIndex, v_lastIndex, num, key ) {
var myTemplate,
htmlData,
cur_item;
if (v_firstIndex < 0) {
return;
}
for ( i = 0; i < num; i++ ) {
if ( v_lastIndex + i > TOTAL_ITEMS ) {
break;
}
cur_item = $( '#li_' + ( v_firstIndex + i ) );
if ( cur_item ) {
/* Make New <LI> element from template. */
myTemplate = $( "#" + o.template );
htmlData = myTemplate.tmpl( dataList[ v_lastIndex + i ] );
/* Copy all data to current item. */
_replace( cur_item, htmlData, key );
/* Set New Position */
( cur_item ).css( 'top', TITLE_H + LINE_H * ( v_lastIndex + 1 + i ) ).attr( 'id', 'li_' + ( v_lastIndex + 1 + i ) );
} else {
break;
}
}
};
// Move older item to bottom
_moveBottomTop = function ( v_firstIndex, v_lastIndex, num, key ) {
var myTemplate,
htmlData,
cur_item;
if ( v_firstIndex < 0 ) {
return;
}
for ( i = 0; i < num; i++ ) {
cur_item = $( '#li_' + ( v_lastIndex - i ) );
if ( cur_item ) {
if ( v_firstIndex - 1 - i < 0 ) {
break;
}
/* Make New <LI> element from template. */
myTemplate = $( "#" + o.template );
htmlData = myTemplate.tmpl( dataList[ v_firstIndex - 1 - i ] );
/* Copy all data to current item. */
_replace( cur_item, htmlData, key );
/* Set New Position */
$( cur_item ).css( 'top', TITLE_H + LINE_H * ( v_firstIndex - 1 - i ) ).attr( 'id', 'li_' + ( v_firstIndex - 1 - i ) );
} else {
break;
}
}
};
/* Matrix to Array function written by Blender@stackoverflow.nnikishi@emich.edu*/
_matrixToArray = function ( matrix ) {
var contents = matrix.substr( 7 );
contents = contents.substr( 0, contents.length - 1 );
return contents.split( ', ' );
};
// Get scroll direction and velocity
/* with Scroll view */
if ( o.scrollview ) {
$el = $( o.id ).parentsUntil( ".ui-page" ).find( ".ui-scrollview-view" );
transformValue = _matrixToArray( $el.css( "-webkit-transform" ) );
curWindowTop = Math.abs( transformValue[ 5 ] ); /* Y vector */
} else {
curWindowTop = $( window ).scrollTop() - LINE_H;
}
cur_num_top_itmes = $( o.id + o.childSelector ).filter( function () {
return (parseInt( $( this ).css( "top" ), 10 ) < curWindowTop );
} ).size();
if ( num_top_items < cur_num_top_itmes ) {
direction = SCROLL_DOWN;
velocity = cur_num_top_itmes - num_top_items;
num_top_items = cur_num_top_itmes;
} else if ( num_top_items > cur_num_top_itmes ) {
direction = SCROLL_UP;
velocity = num_top_items - cur_num_top_itmes;
num_top_items = cur_num_top_itmes;
}
// Move items
if ( direction == SCROLL_DOWN ) {
if ( cur_num_top_itmes > o.page_buf ) {
if ( last_index + velocity > TOTAL_ITEMS ) {
velocity = TOTAL_ITEMS - last_index - 1;
}
/* Prevent scroll touch event while DOM access */
$(document).bind( "touchstart.virtuallist", function (event) {
event.preventDefault();
});
_moveTopBottom( first_index, last_index, velocity, o.dbkey );
first_index += velocity;
last_index += velocity;
num_top_items -= velocity;
/* Unset prevent touch event */
$( document ).unbind( "touchstart.virtuallist" );
}
} else if ( direction == SCROLL_UP ) {
if ( cur_num_top_itmes <= o.page_buf ) {
if ( first_index < velocity ) {
velocity = first_index;
}
/* Prevent scroll touch event while DOM access */
$( document ).bind( "touchstart.virtuallist", function ( event ) {
event.preventDefault();
});
_moveBottomTop( first_index, last_index, velocity, o.dbkey );
first_index -= velocity;
last_index -= velocity;
num_top_items += velocity;
/* Unset prevent touch event */
$( document ).unbind( "touchstart.virtuallist" );
}
if ( first_index < o.page_buf ) {
num_top_items = first_index;
}
}
},
recreate: function ( newArray ) {
var t = this,
o = this.options;
$( o.id ).empty();
TOTAL_ITEMS = newArray.length;
direction = NO_SCROLL;
first_index = 0;
last_index = o.row - 1;
t._pushData( ( o.template ), newArray );
if (o.childSelector == " ul" ) {
$( o.id + " ul" ).swipelist();
}
$( o.id ).virtuallistview();
t._reposition( o );
t.refresh( true );
},
_initList: function () {
var t = this,
o = this.options;
/* After AJAX loading success */
o.dbtable = t.element.data( "dbtable" );
TOTAL_ITEMS = $(window[o.dbtable]).size();
/* Make Gen list by template */
t._pushData( (o.template), window[o.dbtable]);
$( o.id ).parentsUntil( ".ui-page" ).parent().one( "pageshow", o, t._reposition);
/* Scrollview */
$( document ).bind( "scrollstop.virtuallist", t.options, t._scrollmove );
$( window ).bind( "resize.virtuallist", t._resize );
if ( o.childSelector == " ul" ) {
$( o.id + " ul" ).swipelist();
}
t.refresh( true );
},
create: function () {
var o = this.options;
/* external API for AJAX callback */
this._create( "create" );
this._reposition( o );
},
_create: function ( event ) {
var t = this,
o = this.options,
$el = this.element,
shortcutsContainer = $('<div class="ui-virtuallist"/>'),
shortcutsList = $('<ul></ul>'),
dividers = $el.find(':jqmData(role="virtuallistview" )'),
lastListItem = null,
shortcutscroll = this;
// create listview markup
t.element.addClass( function ( i, orig ) {
return orig + " ui-listview ui-virtual-list-container" + ( t.options.inset ? " ui-listview-inset ui-corner-all ui-shadow " : "" );
});
o.id = "#" + $el.attr( "id" );
$( o.id ).bind( "pagehide", function ( e ) {
$( o.id ).empty();
});
/* Scroll view */
if ( $( ".ui-scrollview-clip" ).size() > 0 ) {
o.scrollview = true;
} else {
o.scrollview = false;
}
/* Init list and page buf */
if ( $el.data( "row" ) ) {
o.row = $el.data( "row" );
if ( o.row < MINIMUM_ROW ) {
o.row = MINIMUM_ROW;
}
o.page_buf = parseInt( ( o.row / 2 ), 10 );
}
/* After DB Load complete, Init Vritual list */
if ( $( o.id ).hasClass( "vlLoadSuccess" ) ) {
$( o.id ).empty();
if ( $el.data( "template" ) ) {
o.template = $el.data( "template" );
/* to support swipe list, <li> or <ul> can be main node of virtual list. */
if ( $el.data( "swipelist" ) == true ) {
o.childSelector = " ul";
} else {
o.childSelector = " li";
}
}
/* Set data's unique key */
if ( $el.data( "dbkey" ) ) {
o.datakey = $el.data( "dbkey" );
}
first_index = 0; //first id of <li> element.
last_index = o.row - 1; //last id of <li> element.
t._initList();
}
},
destroy : function () {
var o = this.options;
$( document ).unbind( "scrollstop" );
$( window ).unbind( "resize.virtuallist" );
$( o.id ).empty();
},
_itemApply: function ( $list, item ) {
var $countli = item.find( ".ui-li-count" );
if ( $countli.length ) {
item.addClass( "ui-li-has-count" );
}
$countli.addClass( "ui-btn-up-" + ( $list.jqmData( "counttheme" ) || this.options.countTheme ) + " ui-btn-corner-all" );
// TODO class has to be defined in markup
item.find( "h1, h2, h3, h4, h5, h6" ).addClass( "ui-li-heading" ).end()
.find( "p, dl" ).addClass( "ui-li-desc" ).end()
.find( ">img:eq(0), .ui-link-inherit>img:eq(0)" ).addClass( "ui-li-thumb" ).each( function () {
item.addClass( $( this ).is( ".ui-li-icon" ) ? "ui-li-has-icon" : "ui-li-has-thumb" );
}).end()
.find( ".ui-li-aside" ).each(function () {
var $this = $( this );
$this.prependTo( $this.parent() ); //shift aside to front for css float
} );
},
_removeCorners: function ( li, which ) {
var top = "ui-corner-top ui-corner-tr ui-corner-tl",
bot = "ui-corner-bottom ui-corner-br ui-corner-bl";
li = li.add( li.find( ".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb" ) );
if ( which === "top" ) {
li.removeClass( top );
} else if ( which === "bottom" ) {
li.removeClass( bot );
} else {
li.removeClass( top + " " + bot );
}
},
_refreshCorners: function ( create ) {
var $li,
$visibleli,
$topli,
$bottomli;
if ( this.options.inset ) {
$li = this.element.children( "li" );
// at create time the li are not visible yet so we need to rely on .ui-screen-hidden
$visibleli = create ? $li.not( ".ui-screen-hidden" ) : $li.filter( ":visible" );
this._removeCorners( $li );
// Select the first visible li element
$topli = $visibleli.first()
.addClass( "ui-corner-top" );
$topli.add( $topli.find( ".ui-btn-inner" ) )
.find( ".ui-li-link-alt" )
.addClass( "ui-corner-tr" )
.end()
.find( ".ui-li-thumb" )
.not( ".ui-li-icon" )
.addClass( "ui-corner-tl" );
// Select the last visible li element
$bottomli = $visibleli.last()
.addClass( "ui-corner-bottom" );
$bottomli.add( $bottomli.find( ".ui-btn-inner" ) )
.find( ".ui-li-link-alt" )
.addClass( "ui-corner-br" )
.end()
.find( ".ui-li-thumb" )
.not( ".ui-li-icon" )
.addClass( "ui-corner-bl" );
}
},
refresh: function ( create ) {
this.parentPage = this.element.closest( ".ui-page" );
this._createSubPages();
var o = this.options,
$list = this.element,
self = this,
dividertheme = $list.jqmData( "dividertheme" ) || o.dividerTheme,
listsplittheme = $list.jqmData( "splittheme" ),
listspliticon = $list.jqmData( "spliticon" ),
li = $list.children( "li" ),
counter = $.support.cssPseudoElement || !$.nodeName( $list[ 0 ], "ol" ) ? 0 : 1,
item,
itemClass,
temTheme,
a,
last,
splittheme,
countParent,
icon,
pos,
numli,
itemTheme;
if ( counter ) {
$list.find( ".ui-li-dec" ).remove();
}
for ( pos = 0, numli = li.length; pos < numli; pos++ ) {
item = li.eq( pos );
itemClass = "ui-li";
// If we're creating the element, we update it regardless
if ( create || !item.hasClass( "ui-li" ) ) {
itemTheme = item.jqmData( "theme" ) || o.theme;
a = item.children( "a" );
if ( a.length ) {
icon = item.jqmData( "icon" );
item.buttonMarkup({
wrapperEls: "div",
shadow: false,
corners: false,
iconpos: "right",
/* icon: a.length > 1 || icon === false ? false : icon || "arrow-r",*/
icon: false, /* Remove unnecessary arrow icon */
theme: itemTheme
});
if ( ( icon != false ) && ( a.length == 1 ) ) {
item.addClass( "ui-li-has-arrow" );
}
a.first().addClass( "ui-link-inherit" );
if ( a.length > 1 ) {
itemClass += " ui-li-has-alt";
last = a.last();
splittheme = listsplittheme || last.jqmData( "theme" ) || o.splitTheme;
last.appendTo(item)
.attr( "title", last.getEncodedText() )
.addClass( "ui-li-link-alt" )
.empty()
.buttonMarkup({
shadow: false,
corners: false,
theme: itemTheme,
icon: false,
iconpos: false
})
.find( ".ui-btn-inner" )
.append(
$( "<span />" ).buttonMarkup({
shadow: true,
corners: true,
theme: splittheme,
iconpos: "notext",
icon: listspliticon || last.jqmData( "icon" ) || o.splitIcon
})
);
}
} else if ( item.jqmData( "role" ) === "list-divider" ) {
itemClass += " ui-li-divider ui-btn ui-bar-" + dividertheme;
item.attr( "role", "heading" );
//reset counter when a divider heading is encountered
if ( counter ) {
counter = 1;
}
} else {
itemClass += " ui-li-static ui-body-" + itemTheme;
}
}
if ( counter && itemClass.indexOf( "ui-li-divider" ) < 0 ) {
countParent = item.is( ".ui-li-static:first" ) ? item : item.find( ".ui-link-inherit" );
countParent.addClass( "ui-li-jsnumbering" )
.prepend( "<span class='ui-li-dec'>" + (counter++) + ". </span>" );
}
item.add( item.children( ".ui-btn-inner" ) ).addClass( itemClass );
self._itemApply( $list, item );
}
this._refreshCorners( create );
},
//create a string for ID/subpage url creation
_idStringEscape: function ( str ) {
return str.replace(/\W/g , "-");
},
_createSubPages: function () {
var parentList = this.element,
parentPage = parentList.closest( ".ui-page" ),
parentUrl = parentPage.jqmData( "url" ),
parentId = parentUrl || parentPage[ 0 ][ $.expando ],
parentListId = parentList.attr( "id" ),
o = this.options,
dns = "data-" + $.mobile.ns,
self = this,
persistentFooterID = parentPage.find( ":jqmData(role='footer')" ).jqmData( "id" ),
hasSubPages,
newRemove;
if ( typeof listCountPerPage[ parentId ] === "undefined" ) {
listCountPerPage[ parentId ] = -1;
}
parentListId = parentListId || ++listCountPerPage[ parentId ];
$( parentList.find( "li>ul, li>ol" ).toArray().reverse() ).each(function ( i ) {
var self = this,
list = $( this ),
listId = list.attr( "id" ) || parentListId + "-" + i,
parent = list.parent(),
nodeEls,
title = nodeEls.first().getEncodedText(),//url limits to first 30 chars of text
id = ( parentUrl || "" ) + "&" + $.mobile.subPageUrlKey + "=" + listId,
theme = list.jqmData( "theme" ) || o.theme,
countTheme = list.jqmData( "counttheme" ) || parentList.jqmData( "counttheme" ) || o.countTheme,
newPage,
anchor;
nodeEls = $( list.prevAll().toArray().reverse() );
nodeEls = nodeEls.length ? nodeEls : $( "<span>" + $.trim( parent.contents()[ 0 ].nodeValue ) + "</span>" );
//define hasSubPages for use in later removal
hasSubPages = true;
newPage = list.detach()
.wrap( "<div " + dns + "role='page' " + dns + "url='" + id + "' " + dns + "theme='" + theme + "' " + dns + "count-theme='" + countTheme + "'><div " + dns + "role='content'></div></div>" )
.parent()
.before( "<div " + dns + "role='header' " + dns + "theme='" + o.headerTheme + "'><div class='ui-title'>" + title + "</div></div>" )
.after( persistentFooterID ? $( "<div " + dns + "role='footer' " + dns + "id='" + persistentFooterID + "'>" ) : "" )
.parent()
.appendTo( $.mobile.pageContainer );
newPage.page();
anchor = parent.find('a:first');
if ( !anchor.length ) {
anchor = $( "<a/>" ).html( nodeEls || title ).prependTo( parent.empty() );
}
anchor.attr( "href", "#" + id );
}).virtuallistview();
// on pagehide, remove any nested pages along with the parent page, as long as they aren't active
// and aren't embedded
if ( hasSubPages &&
parentPage.is( ":jqmData(external-page='true')" ) &&
parentPage.data( "page" ).options.domCache === false ) {
newRemove = function ( e, ui ) {
var nextPage = ui.nextPage, npURL;
if ( ui.nextPage ) {
npURL = nextPage.jqmData( "url" );
if ( npURL.indexOf( parentUrl + "&" + $.mobile.subPageUrlKey ) !== 0 ) {
self.childPages().remove();
parentPage.remove();
}
}
};
// unbind the original page remove and replace with our specialized version
parentPage
.unbind( "pagehide.remove" )
.bind( "pagehide.remove", newRemove );
}
},
// TODO sort out a better way to track sub pages of the virtuallistview this is brittle
childPages: function () {
var parentUrl = this.parentPage.jqmData( "url" );
return $( ":jqmData(url^='" + parentUrl + "&" + $.mobile.subPageUrlKey + "')" );
}
});
//auto self-init widgets
$( document ).bind( "pagecreate create", function ( e ) {
$( $.tizen.virtuallistview.prototype.options.initSelector, e.target ).virtuallistview();
});
} ( jQuery ) );
/*!
* Globalize
*
* http://github.com/jquery/globalize
*
* Copyright Software Freedom Conservancy, Inc.
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/
(function( window, undefined ) {
var Globalize,
// private variables
regexHex,
regexInfinity,
regexParseFloat,
regexTrim,
// private JavaScript utility functions
arrayIndexOf,
endsWith,
extend,
isArray,
isFunction,
isObject,
startsWith,
trim,
truncate,
zeroPad,
// private Globalization utility functions
appendPreOrPostMatch,
expandFormat,
formatDate,
formatNumber,
getTokenRegExp,
getEra,
getEraYear,
parseExact,
parseNegativePattern;
// Global variable (Globalize) or CommonJS module (globalize)
Globalize = function( cultureSelector ) {
return new Globalize.prototype.init( cultureSelector );
};
if ( typeof require !== "undefined"
&& typeof exports !== "undefined"
&& typeof module !== "undefined" ) {
// Assume CommonJS
module.exports = Globalize;
} else {
// Export as global variable
window.Globalize = Globalize;
}
Globalize.cultures = {};
Globalize.prototype = {
constructor: Globalize,
init: function( cultureSelector ) {
this.cultures = Globalize.cultures;
this.cultureSelector = cultureSelector;
return this;
}
};
Globalize.prototype.init.prototype = Globalize.prototype;
// 1. When defining a culture, all fields are required except the ones stated as optional.
// 2. Each culture should have a ".calendars" object with at least one calendar named "standard"
// which serves as the default calendar in use by that culture.
// 3. Each culture should have a ".calendar" object which is the current calendar being used,
// it may be dynamically changed at any time to one of the calendars in ".calendars".
Globalize.cultures[ "default" ] = {
// A unique name for the culture in the form <language code>-<country/region code>
name: "en",
// the name of the culture in the english language
englishName: "English",
// the name of the culture in its own language
nativeName: "English",
// whether the culture uses right-to-left text
isRTL: false,
// "language" is used for so-called "specific" cultures.
// For example, the culture "es-CL" means "Spanish, in Chili".
// It represents the Spanish-speaking culture as it is in Chili,
// which might have different formatting rules or even translations
// than Spanish in Spain. A "neutral" culture is one that is not
// specific to a region. For example, the culture "es" is the generic
// Spanish culture, which may be a more generalized version of the language
// that may or may not be what a specific culture expects.
// For a specific culture like "es-CL", the "language" field refers to the
// neutral, generic culture information for the language it is using.
// This is not always a simple matter of the string before the dash.
// For example, the "zh-Hans" culture is netural (Simplified Chinese).
// And the "zh-SG" culture is Simplified Chinese in Singapore, whose lanugage
// field is "zh-CHS", not "zh".
// This field should be used to navigate from a specific culture to it's
// more general, neutral culture. If a culture is already as general as it
// can get, the language may refer to itself.
language: "en",
// numberFormat defines general number formatting rules, like the digits in
// each grouping, the group separator, and how negative numbers are displayed.
numberFormat: {
// [negativePattern]
// Note, numberFormat.pattern has no "positivePattern" unlike percent and currency,
// but is still defined as an array for consistency with them.
// negativePattern: one of "(n)|-n|- n|n-|n -"
pattern: [ "-n" ],
// number of decimal places normally shown
decimals: 2,
// string that separates number groups, as in 1,000,000
",": ",",
// string that separates a number from the fractional portion, as in 1.99
".": ".",
// array of numbers indicating the size of each number group.
// TODO: more detailed description and example
groupSizes: [ 3 ],
// symbol used for positive numbers
"+": "+",
// symbol used for negative numbers
"-": "-",
// symbol used for NaN (Not-A-Number)
NaN: "NaN",
// symbol used for Negative Infinity
negativeInfinity: "-Infinity",
// symbol used for Positive Infinity
positiveInfinity: "Infinity",
percent: {
// [negativePattern, positivePattern]
// negativePattern: one of "-n %|-n%|-%n|%-n|%n-|n-%|n%-|-% n|n %-|% n-|% -n|n- %"
// positivePattern: one of "n %|n%|%n|% n"
pattern: [ "-n %", "n %" ],
// number of decimal places normally shown
decimals: 2,
// array of numbers indicating the size of each number group.
// TODO: more detailed description and example
groupSizes: [ 3 ],
// string that separates number groups, as in 1,000,000
",": ",",
// string that separates a number from the fractional portion, as in 1.99
".": ".",
// symbol used to represent a percentage
symbol: "%"
},
currency: {
// [negativePattern, positivePattern]
// negativePattern: one of "($n)|-$n|$-n|$n-|(n$)|-n$|n-$|n$-|-n $|-$ n|n $-|$ n-|$ -n|n- $|($ n)|(n $)"
// positivePattern: one of "$n|n$|$ n|n $"
pattern: [ "($n)", "$n" ],
// number of decimal places normally shown
decimals: 2,
// array of numbers indicating the size of each number group.
// TODO: more detailed description and example
groupSizes: [ 3 ],
// string that separates number groups, as in 1,000,000
",": ",",
// string that separates a number from the fractional portion, as in 1.99
".": ".",
// symbol used to represent currency
symbol: "$"
}
},
// calendars defines all the possible calendars used by this culture.
// There should be at least one defined with name "standard", and is the default
// calendar used by the culture.
// A calendar contains information about how dates are formatted, information about
// the calendar's eras, a standard set of the date formats,
// translations for day and month names, and if the calendar is not based on the Gregorian
// calendar, conversion functions to and from the Gregorian calendar.
calendars: {
standard: {
// name that identifies the type of calendar this is
name: "Gregorian_USEnglish",
// separator of parts of a date (e.g. "/" in 11/05/1955)
"/": "/",
// separator of parts of a time (e.g. ":" in 05:44 PM)
":": ":",
// the first day of the week (0 = Sunday, 1 = Monday, etc)
firstDay: 0,
days: {
// full day names
names: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
// abbreviated day names
namesAbbr: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
// shortest day names
namesShort: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ]
},
months: {
// full month names (13 months for lunar calendards -- 13th month should be "" if not lunar)
names: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "" ],
// abbreviated month names
namesAbbr: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" ]
},
// AM and PM designators in one of these forms:
// The usual view, and the upper and lower case versions
// [ standard, lowercase, uppercase ]
// The culture does not use AM or PM (likely all standard date formats use 24 hour time)
// null
AM: [ "AM", "am", "AM" ],
PM: [ "PM", "pm", "PM" ],
eras: [
// eras in reverse chronological order.
// name: the name of the era in this culture (e.g. A.D., C.E.)
// start: when the era starts in ticks (gregorian, gmt), null if it is the earliest supported era.
// offset: offset in years from gregorian calendar
{
"name": "A.D.",
"start": null,
"offset": 0
}
],
// when a two digit year is given, it will never be parsed as a four digit
// year greater than this year (in the appropriate era for the culture)
// Set it as a full year (e.g. 2029) or use an offset format starting from
// the current year: "+19" would correspond to 2029 if the current year 2010.
twoDigitYearMax: 2029,
// set of predefined date and time patterns used by the culture
// these represent the format someone in this culture would expect
// to see given the portions of the date that are shown.
patterns: {
// short date pattern
d: "M/d/yyyy",
// long date pattern
D: "dddd, MMMM dd, yyyy",
// short time pattern
t: "h:mm tt",
// long time pattern
T: "h:mm:ss tt",
// long date, short time pattern
f: "dddd, MMMM dd, yyyy h:mm tt",
// long date, long time pattern
F: "dddd, MMMM dd, yyyy h:mm:ss tt",
// month/day pattern
M: "MMMM dd",
// month/year pattern
Y: "yyyy MMMM",
// S is a sortable format that does not vary by culture
S: "yyyy\u0027-\u0027MM\u0027-\u0027dd\u0027T\u0027HH\u0027:\u0027mm\u0027:\u0027ss"
}
// optional fields for each calendar:
/*
monthsGenitive:
Same as months but used when the day preceeds the month.
Omit if the culture has no genitive distinction in month names.
For an explaination of genitive months, see http://blogs.msdn.com/michkap/archive/2004/12/25/332259.aspx
convert:
Allows for the support of non-gregorian based calendars. This convert object is used to
to convert a date to and from a gregorian calendar date to handle parsing and formatting.
The two functions:
fromGregorian( date )
Given the date as a parameter, return an array with parts [ year, month, day ]
corresponding to the non-gregorian based year, month, and day for the calendar.
toGregorian( year, month, day )
Given the non-gregorian year, month, and day, return a new Date() object
set to the corresponding date in the gregorian calendar.
*/
}
},
// For localized strings
messages: {}
};
Globalize.cultures[ "default" ].calendar = Globalize.cultures[ "default" ].calendars.standard;
Globalize.cultures[ "en" ] = Globalize.cultures[ "default" ];
Globalize.cultureSelector = "en";
//
// private variables
//
regexHex = /^0x[a-f0-9]+$/i;
regexInfinity = /^[+-]?infinity$/i;
regexParseFloat = /^[+-]?\d*\.?\d*(e[+-]?\d+)?$/;
regexTrim = /^\s+|\s+$/g;
//
// private JavaScript utility functions
//
arrayIndexOf = function( array, item ) {
if ( array.indexOf ) {
return array.indexOf( item );
}
for ( var i = 0, length = array.length; i < length; i++ ) {
if ( array[i] === item ) {
return i;
}
}
return -1;
};
endsWith = function( value, pattern ) {
return value.substr( value.length - pattern.length ) === pattern;
};
extend = function( deep ) {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !isFunction(target) ) {
target = {};
}
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) {
continue;
}
// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( isObject(copy) || (copyIsArray = isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && isArray(src) ? src : [];
} else {
clone = src && isObject(src) ? src : {};
}
// Never move original objects, clone them
target[ name ] = extend( deep, clone, copy );
// Don't bring in undefined values
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};
isArray = Array.isArray || function( obj ) {
return Object.prototype.toString.call( obj ) === "[object Array]";
};
isFunction = function( obj ) {
return Object.prototype.toString.call( obj ) === "[object Function]";
};
isObject = function( obj ) {
return Object.prototype.toString.call( obj ) === "[object Object]";
};
startsWith = function( value, pattern ) {
return value.indexOf( pattern ) === 0;
};
trim = function( value ) {
return ( value + "" ).replace( regexTrim, "" );
};
truncate = function( value ) {
if ( isNaN( value ) ) {
return NaN;
}
return Math[ value < 0 ? "ceil" : "floor" ]( value );
};
zeroPad = function( str, count, left ) {
var l;
for ( l = str.length; l < count; l += 1 ) {
str = ( left ? ("0" + str) : (str + "0") );
}
return str;
};
//
// private Globalization utility functions
//
appendPreOrPostMatch = function( preMatch, strings ) {
// appends pre- and post- token match strings while removing escaped characters.
// Returns a single quote count which is used to determine if the token occurs
// in a string literal.
var quoteCount = 0,
escaped = false;
for ( var i = 0, il = preMatch.length; i < il; i++ ) {
var c = preMatch.charAt( i );
switch ( c ) {
case "\'":
if ( escaped ) {
strings.push( "\'" );
}
else {
quoteCount++;
}
escaped = false;
break;
case "\\":
if ( escaped ) {
strings.push( "\\" );
}
escaped = !escaped;
break;
default:
strings.push( c );
escaped = false;
break;
}
}
return quoteCount;
};
expandFormat = function( cal, format ) {
// expands unspecified or single character date formats into the full pattern.
format = format || "F";
var pattern,
patterns = cal.patterns,
len = format.length;
if ( len === 1 ) {
pattern = patterns[ format ];
if ( !pattern ) {
throw "Invalid date format string \'" + format + "\'.";
}
format = pattern;
}
else if ( len === 2 && format.charAt(0) === "%" ) {
// %X escape format -- intended as a custom format string that is only one character, not a built-in format.
format = format.charAt( 1 );
}
return format;
};
formatDate = function( value, format, culture ) {
var cal = culture.calendar,
convert = cal.convert;
if ( !format || !format.length || format === "i" ) {
var ret;
if ( culture && culture.name.length ) {
if ( convert ) {
// non-gregorian calendar, so we cannot use built-in toLocaleString()
ret = formatDate( value, cal.patterns.F, culture );
}
else {
var eraDate = new Date( value.getTime() ),
era = getEra( value, cal.eras );
eraDate.setFullYear( getEraYear(value, cal, era) );
ret = eraDate.toLocaleString();
}
}
else {
ret = value.toString();
}
return ret;
}
var eras = cal.eras,
sortable = format === "s";
format = expandFormat( cal, format );
// Start with an empty string
ret = [];
var hour,
zeros = [ "0", "00", "000" ],
foundDay,
checkedDay,
dayPartRegExp = /([^d]|^)(d|dd)([^d]|$)/g,
quoteCount = 0,
tokenRegExp = getTokenRegExp(),
converted;
function padZeros( num, c ) {
var r, s = num + "";
if ( c > 1 && s.length < c ) {
r = ( zeros[c - 2] + s);
return r.substr( r.length - c, c );
}
else {
r = s;
}
return r;
}
function hasDay() {
if ( foundDay || checkedDay ) {
return foundDay;
}
foundDay = dayPartRegExp.test( format );
checkedDay = true;
return foundDay;
}
function getPart( date, part ) {
if ( converted ) {
return converted[ part ];
}
switch ( part ) {
case 0: return date.getFullYear();
case 1: return date.getMonth();
case 2: return date.getDate();
}
}
if ( !sortable && convert ) {
converted = convert.fromGregorian( value );
}
for ( ; ; ) {
// Save the current index
var index = tokenRegExp.lastIndex,
// Look for the next pattern
ar = tokenRegExp.exec( format );
// Append the text before the pattern (or the end of the string if not found)
var preMatch = format.slice( index, ar ? ar.index : format.length );
quoteCount += appendPreOrPostMatch( preMatch, ret );
if ( !ar ) {
break;
}
// do not replace any matches that occur inside a string literal.
if ( quoteCount % 2 ) {
ret.push( ar[0] );
continue;
}
var current = ar[ 0 ],
clength = current.length;
switch ( current ) {
case "ddd":
//Day of the week, as a three-letter abbreviation
case "dddd":
// Day of the week, using the full name
var names = ( clength === 3 ) ? cal.days.namesAbbr : cal.days.names;
ret.push( names[value.getDay()] );
break;
case "d":
// Day of month, without leading zero for single-digit days
case "dd":
// Day of month, with leading zero for single-digit days
foundDay = true;
ret.push(
padZeros( getPart(value, 2), clength )
);
break;
case "MMM":
// Month, as a three-letter abbreviation
case "MMMM":
// Month, using the full name
var part = getPart( value, 1 );
ret.push(
( cal.monthsGenitive && hasDay() )
?
cal.monthsGenitive[ clength === 3 ? "namesAbbr" : "names" ][ part ]
:
cal.months[ clength === 3 ? "namesAbbr" : "names" ][ part ]
);
break;
case "M":
// Month, as digits, with no leading zero for single-digit months
case "MM":
// Month, as digits, with leading zero for single-digit months
ret.push(
padZeros( getPart(value, 1) + 1, clength )
);
break;
case "y":
// Year, as two digits, but with no leading zero for years less than 10
case "yy":
// Year, as two digits, with leading zero for years less than 10
case "yyyy":
// Year represented by four full digits
part = converted ? converted[ 0 ] : getEraYear( value, cal, getEra(value, eras), sortable );
if ( clength < 4 ) {
part = part % 100;
}
ret.push(
padZeros( part, clength )
);
break;
case "h":
// Hours with no leading zero for single-digit hours, using 12-hour clock
case "hh":
// Hours with leading zero for single-digit hours, using 12-hour clock
hour = value.getHours() % 12;
if ( hour === 0 ) hour = 12;
ret.push(
padZeros( hour, clength )
);
break;
case "H":
// Hours with no leading zero for single-digit hours, using 24-hour clock
case "HH":
// Hours with leading zero for single-digit hours, using 24-hour clock
ret.push(
padZeros( value.getHours(), clength )
);
break;
case "m":
// Minutes with no leading zero for single-digit minutes
case "mm":
// Minutes with leading zero for single-digit minutes
ret.push(
padZeros( value.getMinutes(), clength )
);
break;
case "s":
// Seconds with no leading zero for single-digit seconds
case "ss":
// Seconds with leading zero for single-digit seconds
ret.push(
padZeros( value.getSeconds(), clength )
);
break;
case "t":
// One character am/pm indicator ("a" or "p")
case "tt":
// Multicharacter am/pm indicator
part = value.getHours() < 12 ? ( cal.AM ? cal.AM[0] : " " ) : ( cal.PM ? cal.PM[0] : " " );
ret.push( clength === 1 ? part.charAt(0) : part );
break;
case "f":
// Deciseconds
case "ff":
// Centiseconds
case "fff":
// Milliseconds
ret.push(
padZeros( value.getMilliseconds(), 3 ).substr( 0, clength )
);
break;
case "z":
// Time zone offset, no leading zero
case "zz":
// Time zone offset with leading zero
hour = value.getTimezoneOffset() / 60;
ret.push(
( hour <= 0 ? "+" : "-" ) + padZeros( Math.floor(Math.abs(hour)), clength )
);
break;
case "zzz":
// Time zone offset with leading zero
hour = value.getTimezoneOffset() / 60;
ret.push(
( hour <= 0 ? "+" : "-" ) + padZeros( Math.floor(Math.abs(hour)), 2 )
// Hard coded ":" separator, rather than using cal.TimeSeparator
// Repeated here for consistency, plus ":" was already assumed in date parsing.
+ ":" + padZeros( Math.abs(value.getTimezoneOffset() % 60), 2 )
);
break;
case "g":
case "gg":
if ( cal.eras ) {
ret.push(
cal.eras[ getEra(value, eras) ].name
);
}
break;
case "/":
ret.push( cal["/"] );
break;
default:
throw "Invalid date format pattern \'" + current + "\'.";
break;
}
}
return ret.join( "" );
};
// formatNumber
(function() {
var expandNumber;
expandNumber = function( number, precision, formatInfo ) {
var groupSizes = formatInfo.groupSizes,
curSize = groupSizes[ 0 ],
curGroupIndex = 1,
factor = Math.pow( 10, precision ),
rounded = Math.round( number * factor ) / factor;
if ( !isFinite(rounded) ) {
rounded = number;
}
number = rounded;
var numberString = number+"",
right = "",
split = numberString.split( /e/i ),
exponent = split.length > 1 ? parseInt( split[1], 10 ) : 0;
numberString = split[ 0 ];
split = numberString.split( "." );
numberString = split[ 0 ];
right = split.length > 1 ? split[ 1 ] : "";
var l;
if ( exponent > 0 ) {
right = zeroPad( right, exponent, false );
numberString += right.slice( 0, exponent );
right = right.substr( exponent );
}
else if ( exponent < 0 ) {
exponent = -exponent;
numberString = zeroPad( numberString, exponent + 1 );
right = numberString.slice( -exponent, numberString.length ) + right;
numberString = numberString.slice( 0, -exponent );
}
if ( precision > 0 ) {
right = formatInfo[ "." ] +
( (right.length > precision) ? right.slice(0, precision) : zeroPad(right, precision) );
}
else {
right = "";
}
var stringIndex = numberString.length - 1,
sep = formatInfo[ "," ],
ret = "";
while ( stringIndex >= 0 ) {
if ( curSize === 0 || curSize > stringIndex ) {
return numberString.slice( 0, stringIndex + 1 ) + ( ret.length ? (sep + ret + right) : right );
}
ret = numberString.slice( stringIndex - curSize + 1, stringIndex + 1 ) + ( ret.length ? (sep + ret) : "" );
stringIndex -= curSize;
if ( curGroupIndex < groupSizes.length ) {
curSize = groupSizes[ curGroupIndex ];
curGroupIndex++;
}
}
return numberString.slice( 0, stringIndex + 1 ) + sep + ret + right;
};
formatNumber = function( value, format, culture ) {
if ( !isFinite(value) ) {
if ( value === Infinity ) {
return culture.numberFormat.positiveInfinity;
}
if ( value === -Infinity ) {
return culture.numberFormat.negativeInfinity;
}
return culture.numberFormat.NaN;
}
if ( !format || format === "i" ) {
return culture.name.length ? value.toLocaleString() : value.toString();
}
format = format || "D";
var nf = culture.numberFormat,
number = Math.abs( value ),
precision = -1,
pattern;
if ( format.length > 1 ) precision = parseInt( format.slice(1), 10 );
var current = format.charAt( 0 ).toUpperCase(),
formatInfo;
switch ( current ) {
case "D":
pattern = "n";
number = truncate( number );
if ( precision !== -1 ) {
number = zeroPad( "" + number, precision, true );
}
if ( value < 0 ) number = "-" + number;
break;
case "N":
formatInfo = nf;
// fall through
case "C":
formatInfo = formatInfo || nf.currency;
// fall through
case "P":
formatInfo = formatInfo || nf.percent;
pattern = value < 0 ? formatInfo.pattern[ 0 ] : ( formatInfo.pattern[1] || "n" );
if ( precision === -1 ) precision = formatInfo.decimals;
number = expandNumber( number * (current === "P" ? 100 : 1), precision, formatInfo );
break;
default:
throw "Bad number format specifier: " + current;
}
var patternParts = /n|\$|-|%/g,
ret = "";
for ( ; ; ) {
var index = patternParts.lastIndex,
ar = patternParts.exec( pattern );
ret += pattern.slice( index, ar ? ar.index : pattern.length );
if ( !ar ) {
break;
}
switch ( ar[0] ) {
case "n":
ret += number;
break;
case "$":
ret += nf.currency.symbol;
break;
case "-":
// don't make 0 negative
if ( /[1-9]/.test(number) ) {
ret += nf[ "-" ];
}
break;
case "%":
ret += nf.percent.symbol;
break;
}
}
return ret;
};
}());
getTokenRegExp = function() {
// regular expression for matching date and time tokens in format strings.
return /\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g;
};
getEra = function( date, eras ) {
if ( !eras ) return 0;
var start, ticks = date.getTime();
for ( var i = 0, l = eras.length; i < l; i++ ) {
start = eras[ i ].start;
if ( start === null || ticks >= start ) {
return i;
}
}
return 0;
};
getEraYear = function( date, cal, era, sortable ) {
var year = date.getFullYear();
if ( !sortable && cal.eras ) {
// convert normal gregorian year to era-shifted gregorian
// year by subtracting the era offset
year -= cal.eras[ era ].offset;
}
return year;
};
// parseExact
(function() {
var expandYear,
getDayIndex,
getMonthIndex,
getParseRegExp,
outOfRange,
toUpper,
toUpperArray;
expandYear = function( cal, year ) {
// expands 2-digit year into 4 digits.
if ( year < 100 ) {
var now = new Date(),
era = getEra( now ),
curr = getEraYear( now, cal, era ),
twoDigitYearMax = cal.twoDigitYearMax;
twoDigitYearMax = typeof twoDigitYearMax === "string" ? new Date().getFullYear() % 100 + parseInt( twoDigitYearMax, 10 ) : twoDigitYearMax;
year += curr - ( curr % 100 );
if ( year > twoDigitYearMax ) {
year -= 100;
}
}
return year;
};
getDayIndex = function ( cal, value, abbr ) {
var ret,
days = cal.days,
upperDays = cal._upperDays;
if ( !upperDays ) {
cal._upperDays = upperDays = [
toUpperArray( days.names ),
toUpperArray( days.namesAbbr ),
toUpperArray( days.namesShort )
];
}
value = toUpper( value );
if ( abbr ) {
ret = arrayIndexOf( upperDays[1], value );
if ( ret === -1 ) {
ret = arrayIndexOf( upperDays[2], value );
}
}
else {
ret = arrayIndexOf( upperDays[0], value );
}
return ret;
};
getMonthIndex = function( cal, value, abbr ) {
var months = cal.months,
monthsGen = cal.monthsGenitive || cal.months,
upperMonths = cal._upperMonths,
upperMonthsGen = cal._upperMonthsGen;
if ( !upperMonths ) {
cal._upperMonths = upperMonths = [
toUpperArray( months.names ),
toUpperArray( months.namesAbbr )
];
cal._upperMonthsGen = upperMonthsGen = [
toUpperArray( monthsGen.names ),
toUpperArray( monthsGen.namesAbbr )
];
}
value = toUpper( value );
var i = arrayIndexOf( abbr ? upperMonths[1] : upperMonths[0], value );
if ( i < 0 ) {
i = arrayIndexOf( abbr ? upperMonthsGen[1] : upperMonthsGen[0], value );
}
return i;
};
getParseRegExp = function( cal, format ) {
// converts a format string into a regular expression with groups that
// can be used to extract date fields from a date string.
// check for a cached parse regex.
var re = cal._parseRegExp;
if ( !re ) {
cal._parseRegExp = re = {};
}
else {
var reFormat = re[ format ];
if ( reFormat ) {
return reFormat;
}
}
// expand single digit formats, then escape regular expression characters.
var expFormat = expandFormat( cal, format ).replace( /([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g, "\\\\$1" ),
regexp = [ "^" ],
groups = [],
index = 0,
quoteCount = 0,
tokenRegExp = getTokenRegExp(),
match;
// iterate through each date token found.
while ( (match = tokenRegExp.exec(expFormat)) !== null ) {
var preMatch = expFormat.slice( index, match.index );
index = tokenRegExp.lastIndex;
// don't replace any matches that occur inside a string literal.
quoteCount += appendPreOrPostMatch( preMatch, regexp );
if ( quoteCount % 2 ) {
regexp.push( match[0] );
continue;
}
// add a regex group for the token.
var m = match[ 0 ],
len = m.length,
add;
switch ( m ) {
case "dddd": case "ddd":
case "MMMM": case "MMM":
case "gg": case "g":
add = "(\\D+)";
break;
case "tt": case "t":
add = "(\\D*)";
break;
case "yyyy":
case "fff":
case "ff":
case "f":
add = "(\\d{" + len + "})";
break;
case "dd": case "d":
case "MM": case "M":
case "yy": case "y":
case "HH": case "H":
case "hh": case "h":
case "mm": case "m":
case "ss": case "s":
add = "(\\d\\d?)";
break;
case "zzz":
add = "([+-]?\\d\\d?:\\d{2})";
break;
case "zz": case "z":
add = "([+-]?\\d\\d?)";
break;
case "/":
add = "(\\" + cal[ "/" ] + ")";
break;
default:
throw "Invalid date format pattern \'" + m + "\'.";
break;
}
if ( add ) {
regexp.push( add );
}
groups.push( match[0] );
}
appendPreOrPostMatch( expFormat.slice(index), regexp );
regexp.push( "$" );
// allow whitespace to differ when matching formats.
var regexpStr = regexp.join( "" ).replace( /\s+/g, "\\s+" ),
parseRegExp = { "regExp": regexpStr, "groups": groups };
// cache the regex for this format.
return re[ format ] = parseRegExp;
};
outOfRange = function( value, low, high ) {
return value < low || value > high;
};
toUpper = function( value ) {
// "he-IL" has non-breaking space in weekday names.
return value.split( "\u00A0" ).join( " " ).toUpperCase();
};
toUpperArray = function( arr ) {
var results = [];
for ( var i = 0, l = arr.length; i < l; i++ ) {
results[ i ] = toUpper( arr[i] );
}
return results;
};
parseExact = function( value, format, culture ) {
// try to parse the date string by matching against the format string
// while using the specified culture for date field names.
value = trim( value );
var cal = culture.calendar,
// convert date formats into regular expressions with groupings.
// use the regexp to determine the input format and extract the date fields.
parseInfo = getParseRegExp( cal, format ),
match = new RegExp( parseInfo.regExp ).exec( value );
if ( match === null ) {
return null;
}
// found a date format that matches the input.
var groups = parseInfo.groups,
era = null, year = null, month = null, date = null, weekDay = null,
hour = 0, hourOffset, min = 0, sec = 0, msec = 0, tzMinOffset = null,
pmHour = false;
// iterate the format groups to extract and set the date fields.
for ( var j = 0, jl = groups.length; j < jl; j++ ) {
var matchGroup = match[ j + 1 ];
if ( matchGroup ) {
var current = groups[ j ],
clength = current.length,
matchInt = parseInt( matchGroup, 10 );
switch ( current ) {
case "dd": case "d":
// Day of month.
date = matchInt;
// check that date is generally in valid range, also checking overflow below.
if ( outOfRange(date, 1, 31) ) return null;
break;
case "MMM": case "MMMM":
month = getMonthIndex( cal, matchGroup, clength === 3 );
if ( outOfRange(month, 0, 11) ) return null;
break;
case "M": case "MM":
// Month.
month = matchInt - 1;
if ( outOfRange(month, 0, 11) ) return null;
break;
case "y": case "yy":
case "yyyy":
year = clength < 4 ? expandYear( cal, matchInt ) : matchInt;
if ( outOfRange(year, 0, 9999) ) return null;
break;
case "h": case "hh":
// Hours (12-hour clock).
hour = matchInt;
if ( hour === 12 ) hour = 0;
if ( outOfRange(hour, 0, 11) ) return null;
break;
case "H": case "HH":
// Hours (24-hour clock).
hour = matchInt;
if ( outOfRange(hour, 0, 23) ) return null;
break;
case "m": case "mm":
// Minutes.
min = matchInt;
if ( outOfRange(min, 0, 59) ) return null;
break;
case "s": case "ss":
// Seconds.
sec = matchInt;
if ( outOfRange(sec, 0, 59) ) return null;
break;
case "tt": case "t":
// AM/PM designator.
// see if it is standard, upper, or lower case PM. If not, ensure it is at least one of
// the AM tokens. If not, fail the parse for this format.
pmHour = cal.PM && ( matchGroup === cal.PM[0] || matchGroup === cal.PM[1] || matchGroup === cal.PM[2] );
if (
!pmHour && (
!cal.AM || ( matchGroup !== cal.AM[0] && matchGroup !== cal.AM[1] && matchGroup !== cal.AM[2] )
)
) return null;
break;
case "f":
// Deciseconds.
case "ff":
// Centiseconds.
case "fff":
// Milliseconds.
msec = matchInt * Math.pow( 10, 3 - clength );
if ( outOfRange(msec, 0, 999) ) return null;
break;
case "ddd":
// Day of week.
case "dddd":
// Day of week.
weekDay = getDayIndex( cal, matchGroup, clength === 3 );
if ( outOfRange(weekDay, 0, 6) ) return null;
break;
case "zzz":
// Time zone offset in +/- hours:min.
var offsets = matchGroup.split( /:/ );
if ( offsets.length !== 2 ) return null;
hourOffset = parseInt( offsets[0], 10 );
if ( outOfRange(hourOffset, -12, 13) ) return null;
var minOffset = parseInt( offsets[1], 10 );
if ( outOfRange(minOffset, 0, 59) ) return null;
tzMinOffset = ( hourOffset * 60 ) + ( startsWith(matchGroup, "-") ? -minOffset : minOffset );
break;
case "z": case "zz":
// Time zone offset in +/- hours.
hourOffset = matchInt;
if ( outOfRange(hourOffset, -12, 13) ) return null;
tzMinOffset = hourOffset * 60;
break;
case "g": case "gg":
var eraName = matchGroup;
if ( !eraName || !cal.eras ) return null;
eraName = trim( eraName.toLowerCase() );
for ( var i = 0, l = cal.eras.length; i < l; i++ ) {
if ( eraName === cal.eras[i].name.toLowerCase() ) {
era = i;
break;
}
}
// could not find an era with that name
if ( era === null ) return null;
break;
}
}
}
var result = new Date(), defaultYear, convert = cal.convert;
defaultYear = convert ? convert.fromGregorian( result )[ 0 ] : result.getFullYear();
if ( year === null ) {
year = defaultYear;
}
else if ( cal.eras ) {
// year must be shifted to normal gregorian year
// but not if year was not specified, its already normal gregorian
// per the main if clause above.
year += cal.eras[( era || 0 )].offset;
}
// set default day and month to 1 and January, so if unspecified, these are the defaults
// instead of the current day/month.
if ( month === null ) {
month = 0;
}
if ( date === null ) {
date = 1;
}
// now have year, month, and date, but in the culture's calendar.
// convert to gregorian if necessary
if ( convert ) {
result = convert.toGregorian( year, month, date );
// conversion failed, must be an invalid match
if ( result === null ) return null;
}
else {
// have to set year, month and date together to avoid overflow based on current date.
result.setFullYear( year, month, date );
// check to see if date overflowed for specified month (only checked 1-31 above).
if ( result.getDate() !== date ) return null;
// invalid day of week.
if ( weekDay !== null && result.getDay() !== weekDay ) {
return null;
}
}
// if pm designator token was found make sure the hours fit the 24-hour clock.
if ( pmHour && hour < 12 ) {
hour += 12;
}
result.setHours( hour, min, sec, msec );
if ( tzMinOffset !== null ) {
// adjust timezone to utc before applying local offset.
var adjustedMin = result.getMinutes() - ( tzMinOffset + result.getTimezoneOffset() );
// Safari limits hours and minutes to the range of -127 to 127. We need to use setHours
// to ensure both these fields will not exceed this range. adjustedMin will range
// somewhere between -1440 and 1500, so we only need to split this into hours.
result.setHours( result.getHours() + parseInt(adjustedMin / 60, 10), adjustedMin % 60 );
}
return result;
};
}());
parseNegativePattern = function( value, nf, negativePattern ) {
var neg = nf[ "-" ],
pos = nf[ "+" ],
ret;
switch ( negativePattern ) {
case "n -":
neg = " " + neg;
pos = " " + pos;
// fall through
case "n-":
if ( endsWith(value, neg) ) {
ret = [ "-", value.substr(0, value.length - neg.length) ];
}
else if ( endsWith(value, pos) ) {
ret = [ "+", value.substr(0, value.length - pos.length) ];
}
break;
case "- n":
neg += " ";
pos += " ";
// fall through
case "-n":
if ( startsWith(value, neg) ) {
ret = [ "-", value.substr(neg.length) ];
}
else if ( startsWith(value, pos) ) {
ret = [ "+", value.substr(pos.length) ];
}
break;
case "(n)":
if ( startsWith(value, "(") && endsWith(value, ")") ) {
ret = [ "-", value.substr(1, value.length - 2) ];
}
break;
}
return ret || [ "", value ];
};
//
// public instance functions
//
Globalize.prototype.findClosestCulture = function( cultureSelector ) {
return Globalize.findClosestCulture.call( this, cultureSelector );
};
Globalize.prototype.format = function( value, format, cultureSelector ) {
return Globalize.format.call( this, value, format, cultureSelector );
};
Globalize.prototype.localize = function( key, cultureSelector ) {
return Globalize.localize.call( this, key, cultureSelector );
};
Globalize.prototype.parseInt = function( value, radix, cultureSelector ) {
return Globalize.parseInt.call( this, value, radix, cultureSelector );
};
Globalize.prototype.parseFloat = function( value, radix, cultureSelector ) {
return Globalize.parseFloat.call( this, value, radix, cultureSelector );
};
Globalize.prototype.culture = function( cultureSelector ) {
return Globalize.culture.call( this, cultureSelector );
};
//
// public singleton functions
//
Globalize.addCultureInfo = function( cultureName, baseCultureName, info ) {
var base = {},
isNew = false;
if ( typeof cultureName !== "string" ) {
// cultureName argument is optional string. If not specified, assume info is first
// and only argument. Specified info deep-extends current culture.
info = cultureName;
cultureName = this.culture().name;
base = this.cultures[ cultureName ];
} else if ( typeof baseCultureName !== "string" ) {
// baseCultureName argument is optional string. If not specified, assume info is second
// argument. Specified info deep-extends specified culture.
// If specified culture does not exist, create by deep-extending default
info = baseCultureName;
isNew = ( this.cultures[ cultureName ] == null );
base = this.cultures[ cultureName ] || this.cultures[ "default" ];
} else {
// cultureName and baseCultureName specified. Assume a new culture is being created
// by deep-extending an specified base culture
isNew = true;
base = this.cultures[ baseCultureName ];
}
this.cultures[ cultureName ] = extend(true, {},
base,
info
);
// Make the standard calendar the current culture if it's a new culture
if ( isNew ) {
this.cultures[ cultureName ].calendar = this.cultures[ cultureName ].calendars.standard;
}
};
Globalize.findClosestCulture = function( name ) {
var match;
if ( !name ) {
return this.findClosestCulture( this.cultureSelector ) || this.cultures[ "default" ];
}
if ( typeof name === "string" ) {
name = name.split( "," );
}
if ( isArray(name) ) {
var lang,
cultures = this.cultures,
list = name,
i, l = list.length,
prioritized = [];
for ( i = 0; i < l; i++ ) {
name = trim( list[i] );
var pri, parts = name.split( ";" );
lang = trim( parts[0] );
if ( parts.length === 1 ) {
pri = 1;
}
else {
name = trim( parts[1] );
if ( name.indexOf("q=") === 0 ) {
name = name.substr( 2 );
pri = parseFloat( name );
pri = isNaN( pri ) ? 0 : pri;
}
else {
pri = 1;
}
}
prioritized.push({ lang: lang, pri: pri });
}
prioritized.sort(function( a, b ) {
return a.pri < b.pri ? 1 : -1;
});
// exact match
for ( i = 0; i < l; i++ ) {
lang = prioritized[ i ].lang;
match = cultures[ lang ];
if ( match ) {
return match;
}
}
// neutral language match
for ( i = 0; i < l; i++ ) {
lang = prioritized[ i ].lang;
do {
var index = lang.lastIndexOf( "-" );
if ( index === -1 ) {
break;
}
// strip off the last part. e.g. en-US => en
lang = lang.substr( 0, index );
match = cultures[ lang ];
if ( match ) {
return match;
}
}
while ( 1 );
}
// last resort: match first culture using that language
for ( i = 0; i < l; i++ ) {
lang = prioritized[ i ].lang;
for ( var cultureKey in cultures ) {
var culture = cultures[ cultureKey ];
if ( culture.language == lang ) {
return culture;
}
}
}
}
else if ( typeof name === "object" ) {
return name;
}
return match || null;
};
Globalize.format = function( value, format, cultureSelector ) {
culture = this.findClosestCulture( cultureSelector );
if ( value instanceof Date ) {
value = formatDate( value, format, culture );
}
else if ( typeof value === "number" ) {
value = formatNumber( value, format, culture );
}
return value;
};
Globalize.localize = function( key, cultureSelector ) {
return this.findClosestCulture( cultureSelector ).messages[ key ] ||
this.cultures[ "default" ].messages[ key ];
};
Globalize.parseDate = function( value, formats, culture ) {
culture = this.findClosestCulture( culture );
var date, prop, patterns;
if ( formats ) {
if ( typeof formats === "string" ) {
formats = [ formats ];
}
if ( formats.length ) {
for ( var i = 0, l = formats.length; i < l; i++ ) {
var format = formats[ i ];
if ( format ) {
date = parseExact( value, format, culture );
if ( date ) {
break;
}
}
}
}
} else {
patterns = culture.calendar.patterns;
for ( prop in patterns ) {
date = parseExact( value, patterns[prop], culture );
if ( date ) {
break;
}
}
}
return date || null;
};
Globalize.parseInt = function( value, radix, cultureSelector ) {
return truncate( Globalize.parseFloat(value, radix, cultureSelector) );
};
Globalize.parseFloat = function( value, radix, cultureSelector ) {
// radix argument is optional
if ( typeof radix !== "number" ) {
cultureSelector = radix;
radix = 10;
}
var culture = this.findClosestCulture( cultureSelector );
var ret = NaN,
nf = culture.numberFormat;
if ( value.indexOf(culture.numberFormat.currency.symbol) > -1 ) {
// remove currency symbol
value = value.replace( culture.numberFormat.currency.symbol, "" );
// replace decimal seperator
value = value.replace( culture.numberFormat.currency["."], culture.numberFormat["."] );
}
// trim leading and trailing whitespace
value = trim( value );
// allow infinity or hexidecimal
if ( regexInfinity.test(value) ) {
ret = parseFloat( value );
}
else if ( !radix && regexHex.test(value) ) {
ret = parseInt( value, 16 );
}
else {
// determine sign and number
var signInfo = parseNegativePattern( value, nf, nf.pattern[0] ),
sign = signInfo[ 0 ],
num = signInfo[ 1 ];
// #44 - try parsing as "(n)"
if ( sign === "" && nf.pattern[0] !== "(n)" ) {
signInfo = parseNegativePattern( value, nf, "(n)" );
sign = signInfo[ 0 ];
num = signInfo[ 1 ];
}
// try parsing as "-n"
if ( sign === "" && nf.pattern[0] !== "-n" ) {
signInfo = parseNegativePattern( value, nf, "-n" );
sign = signInfo[ 0 ];
num = signInfo[ 1 ];
}
sign = sign || "+";
// determine exponent and number
var exponent,
intAndFraction,
exponentPos = num.indexOf( "e" );
if ( exponentPos < 0 ) exponentPos = num.indexOf( "E" );
if ( exponentPos < 0 ) {
intAndFraction = num;
exponent = null;
}
else {
intAndFraction = num.substr( 0, exponentPos );
exponent = num.substr( exponentPos + 1 );
}
// determine decimal position
var integer,
fraction,
decSep = nf[ "." ],
decimalPos = intAndFraction.indexOf( decSep );
if ( decimalPos < 0 ) {
integer = intAndFraction;
fraction = null;
}
else {
integer = intAndFraction.substr( 0, decimalPos );
fraction = intAndFraction.substr( decimalPos + decSep.length );
}
// handle groups (e.g. 1,000,000)
var groupSep = nf[ "," ];
integer = integer.split( groupSep ).join( "" );
var altGroupSep = groupSep.replace( /\u00A0/g, " " );
if ( groupSep !== altGroupSep ) {
integer = integer.split( altGroupSep ).join( "" );
}
// build a natively parsable number string
var p = sign + integer;
if ( fraction !== null ) {
p += "." + fraction;
}
if ( exponent !== null ) {
// exponent itself may have a number patternd
var expSignInfo = parseNegativePattern( exponent, nf, "-n" );
p += "e" + ( expSignInfo[0] || "+" ) + expSignInfo[ 1 ];
}
if ( regexParseFloat.test(p) ) {
ret = parseFloat( p );
}
}
return ret;
};
Globalize.culture = function( cultureSelector ) {
// setter
if ( typeof cultureSelector !== "undefined" ) {
this.cultureSelector = cultureSelector;
}
// getter
return this.findClosestCulture( cultureSelector ) || this.culture[ "default" ];
};
}( this ));
/**
* loader.js : Loader for web-ui-fw
* Refactored from bootstrap.js
*
* By Youmin Ha <youmin.ha@samsung.com>
*
*/
( function ($, Globalize, window, undefined) {
window.S = {
libFileName : "tizen-web-ui-fw(.min)?.js",
frameworkData : {
rootDir: '/usr/lib/tizen-web-ui-fw',
version: '0.1',
theme: "default",
viewportScale: false,
},
util : {
loadScriptSync : function ( scriptPath, successCB, errorCB ) {
$.ajax( {
url: scriptPath,
dataType: 'script',
async: false,
success: successCB,
error: function ( jqXHR, textStatus, errorThrown ) {
if ( errorCB ) {
errorCB( jqXHR, textStatus, errorThrown );
} else {
var ignoreStatusList = [ 404 ]; // 404: not found
if ( -1 == $.inArray( jqXHR.status, ignoreStatusList ) ) {
window.alert( 'Error while loading ' + scriptPath + '\n' + jqXHR.status + ':' + jqXHR.statusText );
} else {
console.log( 'Error while loading ' + scriptPath + '\n' + jqXHR.status + ':' + jqXHR.statusText );
}
}
}
} );
},
getScaleFactor: function ( ) {
var factor = window.scale,
width = 0,
defaultWidth = 720;
if ( !factor ) {
width = screen.width < screen.height ? screen.width : screen.height;
factor = width / defaultWidth;
if ( factor > 1 ) {
// NOTE: some targets(e.g iPad) need to set scale equal or less than 1.0
factor = 1;
}
}
console.log( "ScaleFactor: " + factor );
return factor;
},
isMobileBrowser: function ( ) {
var mobileIdx = window.navigator.appVersion.indexOf("Mobile"),
isMobile = -1 < mobileIdx;
return isMobile;
}
},
css : {
cacheBust: ( document.location.href.match( /debug=true/ ) ) ?
'?cacheBust=' + ( new Date( ) ).getTime( ) :
'',
addElementToHead : function ( elem ) {
var head = document.getElementsByTagName( 'head' )[0];
head.appendChild( elem );
},
load: function ( path ) {
this.addElementToHead( this.makeLink( path + this.cacheBust ) );
},
makeLink : function ( href ) {
var customstylesheetLink = document.createElement( 'link' );
customstylesheetLink.setAttribute( 'rel', 'stylesheet' );
customstylesheetLink.setAttribute( 'href', href );
return customstylesheetLink;
}
},
getParams: function ( ) {
/* Get data-* params from <script> tag, and set S.frameworkData.* values
* Returns true if proper <script> tag is found, or false if not.
*/
// Find current <script> tag element
var scriptElems = document.getElementsByTagName( 'script' ),
val = null,
foundScriptTag = false,
idx,
elem,
src,
tokens,
version_idx;
for ( idx in scriptElems ) {
elem = scriptElems[idx];
src = elem.src ? elem.getAttribute( 'src' ) : undefined;
if (src && src.match( this.libFileName )) {
// Set framework data, only when they are given.
tokens = src.split(/[\/\\]/);
version_idx = -3;
this.frameworkData.rootDir = elem.getAttribute( 'data-framework-root' )
|| tokens.slice( 0, tokens.length + version_idx ).join( '/' )
|| this.frameworkData.rootDir;
this.frameworkData.version = elem.getAttribute( 'data-framework-version' )
|| tokens[ tokens.length + version_idx ]
|| this.frameworkData.version;
this.frameworkData.theme = elem.getAttribute( 'data-framework-theme' )
|| this.frameworkData.theme;
this.frameworkData.viewportScale = "true" === elem.getAttribute( 'data-framework-viewport-scale' ) ? true : this.frameworkData.viewportScale;
foundScriptTag = true;
break;
}
}
return foundScriptTag;
},
loadTheme: function ( ) {
var themePath = [
this.frameworkData.rootDir,
this.frameworkData.version,
'themes',
this.frameworkData.theme
].join( '/' ),
cssPath = [themePath, 'tizen-web-ui-fw-theme.css'].join( '/' ),
jsPath = [themePath, 'theme.js'].join( '/' );
this.css.load( cssPath );
this.util.loadScriptSync( jsPath );
},
/** Load Globalize culture file, and set default culture.
* @param[in] language Language code. ex) en-US, en, ko-KR, ko
* If language is not given, read language from html 'lang' attribute, or from system setting.
*/
loadGlobalizeCulture: function ( language ) {
function getGlobalizeCultureFile( lang ) {
return ['globalize.culture.', lang, '.js'].join( '' );
}
function getGlobalizeCulturePath( self, file ) {
return [
self.frameworkData.rootDir,
self.frameworkData.version,
'js',
'cultures',
file,
].join( '/' );
}
// Get lang, and change country code to uppercase chars.
var self = this,
lang = language
|| $( 'html' ).attr( 'lang' )
|| window.navigator.language.split( '.' )[0] /* Webkit, Safari + workaround for Tizen */
|| window.navigator.userLanguage /* IE */
|| 'en',
countryCode = null,
countryCodeIdx = lang.lastIndexOf('-'),
ignoreCodes = ['Cyrl', 'Latn', 'Mong'], // Not country code!
globalizeCultureFile,
globalizeCulturePath,
neutralLangIndex;
if ( countryCodeIdx != -1 ) { // Found country code!
countryCode = lang.substr( countryCodeIdx + 1 );
if ( ignoreCodes.join( '-' ).indexOf( countryCode ) < 0 ) { // countryCode is not found from ignoreCodes
// Make countryCode to uppercase
lang = [ lang.substr( 0, countryCodeIdx ), countryCode.toUpperCase( ) ].join( '-' );
}
}
globalizeCultureFile = getGlobalizeCultureFile( lang );
globalizeCulturePath = getGlobalizeCulturePath( self, globalizeCultureFile );
neutralLangIndex = lang.lastIndexOf( '-' );
// Run culture script
console.log( 'Run globalize culture: ' + globalizeCulturePath );
this.util.loadScriptSync(
globalizeCulturePath,
null,
function ( jqXHR, textStatus, errorThrown ) { // Failed to load!
if ( jqXHR.status == 404 ) {
// If culture file is not found, run neutral language culture.
// (e.g. en-US --> en)
if ( neutralLangIndex != -1 ) {
var neutralLang = lang.substr( 0, neutralLangIndex ),
neutralCultureFile = getGlobalizeCultureFile( neutralLang ),
neutralCulturePath = getGlobalizeCulturePath( self, neutralCultureFile );
console.log( 'Run globalize culture of neutral lang: ' + neutralCulturePath );
self.util.loadScriptSync( neutralCulturePath );
}
} else {
window.alert( 'Error while loading ' + globalizeCulturePath + '\n' + jqXHR.status + ':' + jqXHR.statusText );
}
}
);
return lang;
},
setGlobalize: function ( ) {
var lang = this.loadGlobalizeCulture( );
// Set culture
// NOTE: It is not needed to set with neutral lang.
// Globalize automatically deals with it.
Globalize.culture( lang );
},
/** Set viewport meta tag for mobile devices.
*
* @param[in] viewportWidth Viewport width. 'device-dpi' is also allowed.
* @param[in] useAutoScale If true, calculate & use scale factor. otherwise, scale factor is 1.
* @param[in] useDeviceDpi If true, add 'target-densityDpi=device-dpi' to viewport meta content.
*/
setViewport: function ( viewportWidth, useAutoScale, useDeviceDpi ) {
var meta,
scale = 1,
head;
// Do nothing if viewport setting code is already in the code.
$( "meta" ).each( function ( ) {
if ( $( this ).attr( "name" ) === "viewport" ) {
console.log( "User set viewport... framework viewport will not be applied." );
meta = this;
return;
}
});
// Set meta tag
meta = document.createElement( "meta" );
if ( meta ) {
scale = useAutoScale ? this.util.getScaleFactor( ) : scale;
meta.name = "viewport";
meta.content = "width=" + viewportWidth + ", initial-scale=" + scale + ", maximum-scale=" + scale + ", user-scalable=0";
if ( useDeviceDpi ) {
meta.content += ", target-densityDpi=device-dpi";
}
console.log( meta.content );
head = document.getElementsByTagName( 'head' ).item( 0 );
head.insertBefore( meta, head.firstChild );
}
},
/** Read body's font-size, scale it, and reset it.
* param[in] desired font-size / base font-size.
*/
scaleBaseFontSize: function ( themeDefaultFontSize, ratio ) {
var scaledFontSize = Math.round( themeDefaultFontSize * ratio );
$( '.ui-mobile' ).css( { 'font-size': scaledFontSize + "px" } );
$( '.ui-mobile').children( 'body' ).css( { 'font-size': scaledFontSize + "px" } );
},
setScaling: function ( ) {
var baseWidth = 720, // NOTE: need to be changed to get the value from theme.
standardWidth = 360,
themeDefaultFontSize = parseInt( $( 'body' ).css( 'font-size' ), 10 );
$( 'body' ).attr( 'data-tizen-theme-default-font-size', themeDefaultFontSize );
if ( this.frameworkData.viewportScale ) {
// Use viewport scaling with base font-size
// NOTE: No font-size setting is needed.
this.setViewport( baseWidth, true, true );
} else {
// Fixed viewport scale(=1.0) with scaled font size
this.setViewport( "device-dpi", false, undefined );
this.scaleBaseFontSize( themeDefaultFontSize, parseFloat( standardWidth / baseWidth ) );
}
}
};
} ( jQuery, window.Globalize, window ) );
// Loader's job list
( function ( S, $, undefined ) {
S.getParams( );
S.loadTheme( );
S.setGlobalize( );
// Turn off JQM's auto initialization option.
// NOTE: This job must be done before domready.
$.mobile.autoInitializePage = false;
$(document).ready( function ( ) {
S.setScaling( );
$.mobile.initializePage( );
});
} ( window.S, jQuery ) );