summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'SemanticForms/libs')
-rw-r--r--SemanticForms/libs/SF_autoedit.js83
-rw-r--r--SemanticForms/libs/SF_autogrow.js53
-rw-r--r--SemanticForms/libs/SF_checkboxes.js57
-rw-r--r--SemanticForms/libs/SF_collapsible.js55
-rw-r--r--SemanticForms/libs/SF_imagePreview.js66
-rw-r--r--SemanticForms/libs/SF_popupform.js829
-rw-r--r--SemanticForms/libs/SF_preview.js213
-rw-r--r--SemanticForms/libs/SF_submit.js197
-rw-r--r--SemanticForms/libs/SF_wikieditor.js42
-rw-r--r--SemanticForms/libs/SemanticForms.js1084
-rw-r--r--SemanticForms/libs/ext.dynatree.js52
-rw-r--r--SemanticForms/libs/ext.sf.js28
-rw-r--r--SemanticForms/libs/ext.sf.select2.base.js271
-rw-r--r--SemanticForms/libs/ext.sf.select2.combobox.js275
-rw-r--r--SemanticForms/libs/ext.sf.select2.tokens.js314
-rw-r--r--SemanticForms/libs/jquery.browser.js46
-rw-r--r--SemanticForms/libs/jquery.dynatree.js3420
-rw-r--r--SemanticForms/libs/jquery.fancybox.js1152
-rw-r--r--SemanticForms/libs/select2.js3378
19 files changed, 0 insertions, 11615 deletions
diff --git a/SemanticForms/libs/SF_autoedit.js b/SemanticForms/libs/SF_autoedit.js
deleted file mode 100644
index 904251c6..00000000
--- a/SemanticForms/libs/SF_autoedit.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * Javascript handler for the autoedit parser function
- *
- * @author Stephan Gambke
- */
-
-/*global confirm */
-
-( function ( $, mw ) {
-
- 'use strict';
-
- var autoEditHandler = function handleAutoEdit(){
-
- if ( mw.config.get( 'wgUserName' ) === null &&
- ! confirm( mw.msg( 'sf_autoedit_anoneditwarning' ) ) ) {
-
- return;
- }
-
- var jtrigger = jQuery( this );
- var jautoedit = jtrigger.closest( '.autoedit' );
- var jresult = jautoedit.find( '.autoedit-result' );
-
- var reload = jtrigger.hasClass( 'reload' );
-
- jtrigger.attr( 'class', 'autoedit-trigger autoedit-trigger-wait' );
- jresult.attr( 'class', 'autoedit-result autoedit-result-wait' );
-
- jresult.text( mw.msg( 'sf-autoedit-wait' ) );
-
-
- // data array to be sent to the server
- var data = {
- action: 'sfautoedit',
- format: 'json'
- };
-
- // add form values to the data
- data.query = jautoedit.find( 'form.autoedit-data' ).serialize();
-
- $.ajax( {
-
- type: 'POST', // request type ( GET or POST )
- url: mw.util.wikiScript( 'api' ), // URL to which the request is sent
- data: data, // data to be sent to the server
- dataType: 'json', // type of data expected back from the server
- success: function ( result ){
- jresult.empty().append( result.responseText );
-
- if ( result.status === 200 ) {
-
- if ( reload ) {
- window.location.reload();
- }
-
- jresult.removeClass( 'autoedit-result-wait' ).addClass( 'autoedit-result-ok' );
- jtrigger.removeClass( 'autoedit-trigger-wait' ).addClass( 'autoedit-trigger-ok' );
- } else {
- jresult.removeClass( 'autoedit-result-wait' ).addClass( 'autoedit-result-error' );
- jtrigger.removeClass( 'autoedit-trigger-wait' ).addClass( 'autoedit-trigger-error' );
- }
- }, // function to be called if the request succeeds
- error: function ( jqXHR, textStatus, errorThrown ) {
- var result = jQuery.parseJSON(jqXHR.responseText);
- var text = result.responseText;
-
- for ( var i = 0; i < result.errors.length; i++ ) {
- text += ' ' + result.errors[i].message;
- }
-
- jresult.empty().append( text );
- jresult.removeClass( 'autoedit-result-wait' ).addClass( 'autoedit-result-error' );
- jtrigger.removeClass( 'autoedit-trigger-wait' ).addClass( 'autoedit-trigger-error' );
- } // function to be called if the request fails
- } );
- };
-
- jQuery( document ).ready( function ( $ ) {
- $( '.autoedit-trigger' ).click( autoEditHandler );
- } );
-
-}( jQuery, mediaWiki ) );
diff --git a/SemanticForms/libs/SF_autogrow.js b/SemanticForms/libs/SF_autogrow.js
deleted file mode 100644
index 2c21a11f..00000000
--- a/SemanticForms/libs/SF_autogrow.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * SF_autogrow.js
- *
- * Allows for 'autogrow' textareas. Based heavily on the 'Autogrow Textarea
- * Plugin' by Jevin O. Sewaruth:
- * http://www.technoreply.com/autogrow-textarea-plugin/
- *
- * Some modifications were made for the code to better work with Semantic
- * Forms.
- *
- * @author Jevin O. Sewaruth
- * @author Yaron Koren
- */
-
-var autoGrowColsDefault = [];
-var autoGrowRowsDefault = [];
-
-function autoGrowSetDefaultValues(textArea) {
- var id = textArea.id;
- autoGrowColsDefault[id] = textArea.cols;
- autoGrowRowsDefault[id] = textArea.rows;
-}
-
-function autoGrow(textArea) {
- var linesCount = 0;
- var lines = textArea.value.split('\n');
-
- for (var i = lines.length-1; i >= 0; --i) {
- linesCount += Math.floor((lines[i].length / autoGrowColsDefault[textArea.id]) + 1);
- }
-
- if (linesCount >= autoGrowRowsDefault[textArea.id]) {
- textArea.rows = linesCount + 1;
- }
- else {
- textArea.rows = autoGrowRowsDefault[textArea.id];
- }
-}
-
-function autoGrowBindEvents(textArea) {
- textArea.onkeyup = function() {
- autoGrow(textArea);
- };
-}
-
-// jQuery method
-jQuery.fn.autoGrow = function() {
- return this.each(function() {
- autoGrowSetDefaultValues(this);
- autoGrowBindEvents(this);
- autoGrow(this);
- });
-};
diff --git a/SemanticForms/libs/SF_checkboxes.js b/SemanticForms/libs/SF_checkboxes.js
deleted file mode 100644
index 019e5021..00000000
--- a/SemanticForms/libs/SF_checkboxes.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * Javascript handler for the checkboxes input type
- *
- * @author Stephan Gambke
- */
-
-( function ( $, mw ) {
-
- 'use strict';
-
- // jQuery plugin that will attach a select all/select none switch to all checkboxes in "this" element
- $.fn.appendSelectionSwitches = function () {
-
- function insertSwitch( switchesWrapper, label, checked ) {
-
- // create a link element that will trigger the selection of all checkboxes
- var link = $( '<a href="#">' + label + '</a>' );
-
- // will be initialized only when the event is triggered to avoid lag during page loading
- var $checkboxes;
-
- // attach an event handler
- link.click( function ( event ) {
-
- event.preventDefault();
-
- // store checkboxes during first method call so the DOM is not searched on every click on the link
- $checkboxes = $checkboxes || switchesWrapper.siblings().find( 'input[type="checkbox"]' );
-
- $checkboxes.prop( 'checked', checked );
- } );
-
- // wrap the link into a span to simplify styling
- var switchWrapper = $('<span class="checkboxSwitch">' ).append( link );
-
- // insert the complete switch into the DOM
- switchesWrapper.append( switchWrapper );
-
- }
-
- this.each( function ( index, element ) {
-
- var switchesWrapper = $( '<span class="checkboxSwitches">' ).prependTo( element );
-
- insertSwitch( switchesWrapper, mw.message( 'sf_forminputs_checkboxes_select_all' ), true );
- insertSwitch( switchesWrapper, mw.message( 'sf_forminputs_checkboxes_select_none' ), false );
-
- } );
-
- return this;
- };
-
- $().ready( function ( $ ) {
- $( '.checkboxesSpan.select-all' ).appendSelectionSwitches();
- } );
-
-}( jQuery, mediaWiki ) );
diff --git a/SemanticForms/libs/SF_collapsible.js b/SemanticForms/libs/SF_collapsible.js
deleted file mode 100644
index c945f407..00000000
--- a/SemanticForms/libs/SF_collapsible.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * SF_collapsible.js
- *
- * Allows for collapsible fieldsets.
- *
- * Based on the 'coolfieldset' jQuery plugin:
- * http://w3shaman.com/article/jquery-plugin-collapsible-fieldset
- */
-
-function sfHideFieldsetContent(obj, options){
- obj.find('div').slideUp(options.speed);
- obj.removeClass("sfExpandedFieldset");
- obj.addClass("sfCollapsedFieldset");
-}
-
-function sfShowFieldsetContent(obj, options){
- obj.find('div').slideDown(options.speed);
- obj.removeClass("sfCollapsedFieldset");
- obj.addClass("sfExpandedFieldset");
-}
-
-jQuery.fn.sfMakeCollapsible = function(options){
- var setting = { collapsed: true, speed: 'medium' };
- jQuery.extend(setting, options);
-
- this.each(function(){
- var fieldset = jQuery(this);
- var legend = fieldset.children('legend');
- if ( setting.collapsed === true ) {
- legend.toggle(
- function(){
- sfShowFieldsetContent(fieldset, setting);
- },
- function(){
- sfHideFieldsetContent(fieldset, setting);
- }
- );
-
- sfHideFieldsetContent(fieldset, {animation:false});
- } else {
- legend.toggle(
- function(){
- sfHideFieldsetContent(fieldset, setting);
- },
- function(){
- sfShowFieldsetContent(fieldset, setting);
- }
- );
- }
- });
-};
-
-jQuery(document).ready(function() {
- jQuery('.sfCollapsibleFieldset').sfMakeCollapsible();
-});
diff --git a/SemanticForms/libs/SF_imagePreview.js b/SemanticForms/libs/SF_imagePreview.js
deleted file mode 100644
index c1f3affc..00000000
--- a/SemanticForms/libs/SF_imagePreview.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * JavaScript for the Semantic Forms MediaWiki extension.
- *
- * @licence GNU GPL v3+
- * @author Jeroen De Dauw <jeroendedauw at gmail dot com>
- */
-
-(function( $ ) {
- var _this = this;
-
- this.getPreviewImage = function( args, callback ) {
- $.getJSON(
- mw.config.get( 'wgScriptPath' ) + '/api.php',
- {
- 'action': 'query',
- 'format': 'json',
- 'prop': 'imageinfo',
- 'iiprop': 'url',
- 'titles': 'File:' + args.title,
- 'iiurlwidth': args.width
- },
- function( data ) {
- if ( data.query && data.query.pages ) {
- var pages = data.query.pages;
-
- for ( var p = 0; p < pages.length; p++ ) {
- var info = pages[p].imageinfo;
- for ( var i = 0; i < info.length; i++ ) {
- callback( info[i].thumburl );
- return;
- }
- }
- }
- callback( false );
- }
- );
- };
-
- $( document ).ready( function() {
- $( '.sfImagePreview' ).each( function( index, domElement ) {
- var $uploadLink = $( domElement );
- var inputId = $uploadLink.attr( 'data-input-id' );
- var $input = $( '#' + inputId );
- var $previewDiv = $( '#' + inputId + '_imagepreview' );
-
- var showPreview = function() {
- _this.getPreviewImage(
- {
- 'title': $input.val(),
- 'width': 200
- },
- function( url ) {
- if ( url === false ) {
- $previewDiv.html( '' );
- }
- else {
- $previewDiv.html( $( '<img />' ).attr( { 'src': url } ) );
- }
- }
- );
- };
-
- $input.change( showPreview );
- } );
- } );
-})( jQuery );
diff --git a/SemanticForms/libs/SF_popupform.js b/SemanticForms/libs/SF_popupform.js
deleted file mode 100644
index 02b0e582..00000000
--- a/SemanticForms/libs/SF_popupform.js
+++ /dev/null
@@ -1,829 +0,0 @@
-/**
- * Javascript code to be used with extension SemanticForms for popup forms.
- *
- * @author Stephan Gambke
- *
- */
-/*global escape*/
-
-// initialise
-jQuery( function() {
-
- // register eventhandlers on 'edit' links and buttons
-
- // register formlink with link
- jQuery('a.popupformlink').click(function(evt){
- return ext.popupform.handlePopupFormLink( this.getAttribute('href'), this );
- });
-
- // register formlink with button
- jQuery( 'form.popupformlink' ).submit(function(evt){
- return ext.popupform.handlePopupFormLink( this.getAttribute( 'action' ), this );
- });
-
-
- // register forminput
- jQuery( 'form.popupforminput' ).submit(function(evt){
- return ext.popupform.handlePopupFormInput( this.getAttribute( 'action' ), this );
- });
-
-});
-
-// create ext if it does not exist yet
-if ( typeof( window.ext ) === "undefined" ) {
- window.ext = {};
-}
-
-window.ext.popupform = new function() {
- var wrapper;
- var background;
- var container;
- var innerContainer;
- var iframe;
- var content;
- var waitIndicator;
- var instance = 0;
-
- var timer;
- var needsRender = true;
-
- var doc;
-
- var brokenBrowser, brokenChrome;
-
- var padding = 20;
-
- function handlePopupFormInput( ptarget, elem ) {
- showForm();
-
- iframe.one( 'load', function(){
- // attach event handler to iframe
- iframe.bind( 'load', handleLoadFrame );
- return false;
- });
-
- elem.target = 'popupform-iframe' + instance;
- return true;
- }
-
- function handlePopupFormLink( ptarget, elem ) {
- showForm();
-
- // store initial readystate
- var readystate = iframe.contents()[0].readyState;
-
- // set up timer for waiting on the document in the iframe to be dom-ready
- // this sucks, but there is no other way to catch that event
- // onload is already too late
- timer = setInterval(function(){
- // if the readystate changed
- if ( readystate !== iframe.contents()[0].readyState ) {
- // store new readystate
- readystate = iframe.contents()[0].readyState;
-
- // if dom is built but document not yet displayed
- if ( readystate === 'interactive' || readystate === 'complete' ) {
- needsRender = false; // flag that rendering is already done
- handleLoadFrame();
- }
- }
- }, 100 );
-
- // fallback in case we did not catch the dom-ready state
- iframe.on('load', function( event ){
- if ( needsRender ) { // rendering not already done?
- handleLoadFrame( event );
- }
- needsRender = true;
- });
-
- if ( elem.tagName == 'FORM' ) {
- elem.target = 'popupform-iframe' + instance;
- return true;
- } else {
- var delim = ptarget.indexOf( '?' );
- var form = document.createElement("form");
-
- form.target = 'popupform-iframe' + instance;
-
- // Do we have parameters?
- if ( delim > 0 ) {
- form.action = ptarget.substr( 0, delim );
- var params = String( ptarget.substr( delim + 1 ) ).split("&");
- for ( var i = 0; i < params.length; ++i ) {
-
- var input = document.createElement("input");
- var param = String( params[i] ).split('=');
- input.type = 'hidden';
- input.name = decodeURIComponent( param[0] );
- input.value = decodeURIComponent( param[1] );
- form.appendChild( input );
- }
- } else {
- form.action = ptarget;
- }
-
- document.getElementsByTagName('body')[0].appendChild(form);
- form.submit();
- document.getElementsByTagName('body')[0].removeChild(form);
-
- return false;
- }
- }
-
- function showForm() {
- instance++;
-
- brokenChrome =
- ( navigator.userAgent.indexOf("Chrome") >= 0 &&
- navigator.platform.indexOf("Linux x86_64") >= 0 );
-
- brokenBrowser= jQuery.browser.msie || brokenChrome;
-
- var maxZIndex = 0;
-
- jQuery("*").each(function() {
- var curr = parseInt( jQuery( this ).css( "z-index" ) );
- maxZIndex = curr > maxZIndex ? curr : maxZIndex;
- });
-
-
- wrapper = jQuery( "<div class='popupform-wrapper' >" );
- background = jQuery( "<div class='popupform-background' >" );
-
- var waitIndicatorWrapper = jQuery( "<div class='popupform-loading'>" );
-
- waitIndicator = jQuery( "<div class='popupform-loadingbg'></div><div class='popupform-loadingfg'></div>" );
-
- var anchor = jQuery( "<div class='popupform-anchor' >" );
-
- container = jQuery( "<div class='popupform-container' >" );
- innerContainer = jQuery( "<div class='popupform-innercontainer' >" );
- iframe = jQuery( "<iframe class='popupform-innerdocument' name='popupform-iframe" + instance + "' id='popupform-iframe" + instance + "' >");
-
- var closeBtn = jQuery( "<div class='popupform-close'></div> " );
-
- // initially hide background and waitIndicator
- if (brokenChrome) {
- background.css("background", "transparent");
- } else {
- background.css("opacity", 0.0);
- }
-
- waitIndicator.hide();
- container.hide();
-
- // insert background and wait indicator into wrapper and all into document
- waitIndicatorWrapper
- .append( waitIndicator );
-
- innerContainer
- .append( iframe );
-
- container
- .append( closeBtn )
- .append( innerContainer );
-
- anchor
- .append(container);
-
- wrapper
- .css( "z-index", maxZIndex + 1 )
- .append( background )
- .append( waitIndicatorWrapper )
- .append( anchor )
- .appendTo( "body" );
-
- // fade background in
- if ( !brokenChrome ) {
- background.fadeTo( 400, 0.3 );
- }
- fadeIn( waitIndicator );
-
- // attach event handler to close button
- closeBtn.click( handleCloseFrame );
- }
-
- function handleLoadFrame() {
- var iframecontents = iframe.contents();
-
- var containerAlreadyVisible = container.is( ':visible' );
-
- if ( !containerAlreadyVisible ) {
- // no need to hide it again
- if ( brokenBrowser ) {
- container[0].style.visibility = "hidden";
- } else {
- container[0].style.opacity = 0;
- }
- }
-
- container.show();
-
- // GuMaxDD has #content but keeps headlines in #gumax-content-body
- content = iframecontents.find("#gumax-content-body");
-
- // normal skins use #content (e.g. Vector, Monobook)
- if ( content.length === 0 ) {
- content = iframecontents.find("#content");
- }
-
- // some skins use #mw_content (e.g. Modern)
- if ( content.length === 0 ) {
- content = iframecontents.find("#mw_content");
- }
-
- var iframebody = content.closest("body");
- var iframedoc = iframebody.parent();
-
- // this is not a normal MW page (or it uses an unknown skin)
- if ( content.length === 0 ) {
- content = iframebody;
- }
-
- // the huge left margin looks ugly in Vector, reduce it
- // (How does this look for other skins?)
- var siblings = content
- .css( {
- margin: 0,
- padding: padding,
- width: "auto",
- height: "auto",
- minWidth: "0px",
- minHeight:"0px",
-// overflow: "visible",
-// position: "relative",
-// top: "0",
-// left: "0",
- border: "none"
- } )
- .parentsUntil('html')
- .css( {
- margin: 0,
- padding: 0,
- width: "auto",
- height: "auto",
- minWidth: "0px",
- minHeight: "0px",
- "float": "none", // Cavendish skin uses floating -> unfloat content
-// position: "relative",
-// top: "0",
-// left: "0",
- background: "transparent"
- })
- .andSelf().siblings();
-
- iframedoc.height('100%').width('100%');
- iframebody.height('100%').width('100%');
-
- if ( jQuery.browser.msie && jQuery.browser.version < "8" ) {
- siblings.hide();
- } else {
- siblings
- .each( function(){
- var elem = jQuery(this);
-
- // TODO: Does this really help?
- if ( getStyle(this, "display") != "none" && ! (
- ( this.offsetLeft + elem.outerWidth(true) < 0 ) || // left of document
- ( this.offsetTop + elem.outerHeight(true) < 0 ) || // above document
- ( this.offsetLeft > 100000 ) || // right of document
- ( this.offsetTop > 100000 ) // below document
- )
- ) {
-
- jQuery(this).hide();
- // css({
- // height : "0px",
- // width : "0px",
- // minWidth : "0px",
- // minHeight : "0px",
- // margin : "0px",
- // padding : "0px"
- // border : "none",
- // overflow: "hidden"
- // //position: "static"
- // });
- }
- if ( ( this.offsetLeft + elem.outerWidth() < 0 ) ||
- ( this.offsetTop + elem.outerHeight() < 0 )
- ) {
- this.style.left = (-elem.outerWidth(true)) + "px";
- this.style.top = (-elem.outerHeight(true)) + "px";
- }
- });
- //.children().css("position", "static");
- }
-
- container.show();
-
- // adjust frame size to dimensions just calculated
- adjustFrameSize();
-
- // and attach event handler to adjust frame size every time the window
- // size changes
- jQuery( window ).resize( function() {
- adjustFrameSize();
- } );
-
- //interval = setInterval(adjustFrameSize, 100);
-
- var form = content.find("#sfForm");
- var innerwdw = document.getElementById( 'popupform-iframe' + instance ).contentWindow;
- var innerJ = innerwdw.jQuery;
-
- // if we have a form and it is not a RunQuery form
- if (form.length > 0 && ( typeof form[0].wpRunQuery === 'undefined') ) {
- var submitok = false;
- var innersubmitprocessed = false;
-
- // catch form submit event
- form
- .bind( "submit", function( event ){
- var interval = setInterval(function(){
- if ( innersubmitprocessed ) {
- clearInterval( interval );
- innersubmitprocessed = false;
- if ( submitok ) {
- handleSubmitData( event );
- }
- }
-
- }, 10);
- event.stopPropagation();
- return false;
- });
-
- // catch inner form submit event
- if ( innerJ ) {
- innerwdw.jQuery(form[0])
- .bind( "submit", function( event ) {
- submitok = event.result;
- innersubmitprocessed = true;
- return false;
- });
- } else {
- submitok = true;
- innersubmitprocessed = true;
- }
- }
-
- if (innerJ) {
- // FIXME: Why did I put this in?
- innerwdw.jQuery( innerwdw[0] ).unload(function (event) {
- return false;
- });
-
- //
- content.bind( 'click', function() {
- var foundQueue = false;
- innerJ('*', content[0]).each( function() {
- if ( innerJ(this).queue().length > 0 ) {
- foundQueue = true;
- innerJ(this).queue( function(){
- setTimeout( adjustFrameSize, 100, true );
- innerJ(this).dequeue();
- });
- }
- });
- if ( ! foundQueue ) {
- adjustFrameSize( true );
- }
- return true;
- });
- } else {
- content.bind( 'click', function() {
- adjustFrameSize( true );
- });
- }
-
- // find all links. Have to use inner jQuery so event.result below
- // reflects the result of inner event handlers. We (hopefully) come last
- // in the chain of event handlers as we only attach when the frame is
- // already completely loaded, i.e. every inner event handler is already
- // attached.
- var allLinks = (innerJ)?innerJ("a[href]"):jQuery("a[href]");
-
- // catch 'Cancel'-Link (and other 'back'-links) and close frame instead of going back
- var backlinks = allLinks.filter('a[href="javascript:history.go(-1);"]');
- backlinks.click(handleCloseFrame);
-
- // promote any other links to open in main window, prevent nested browsing
- allLinks
- .not('a[href*="javascript:"]') // scripted links
- .not('a[target]') // targeted links
- .not('a[href^="#"]') // local links
- .not('a.sfFancyBox') // link to file upload
- .click(function(event){
- if ( event.result !== false ) { // if not already caught by somebody else
- closeFrameAndFollowLink( event.target.getAttribute('href') );
- }
- return false;
- });
-
- // finally show the frame, but only if it is not already visible
- if ( ! containerAlreadyVisible ) {
- fadeOut ( waitIndicator, function(){
- fadeTo( container, 400, 1 );
- });
- }
-
- return false;
- }
-
- function handleSubmitData( event ){
- fadeOut( container, function() {
- fadeIn( waitIndicator );
- });
-
- var form = jQuery( event.target );
- var formdata = form.serialize() + "&wpSave=" + escape(form.find("#wpSave").attr("value"));
-
- // Send form data off. SF will send back a fake edit page
- //
- // Normally we should check this.action first and only if it is empty
- // revert to this.ownerDocument.URL. Tough luck, IE does not return an
- // empty action but fills in some bogus
- jQuery.post( event.target.ownerDocument.URL , formdata, handleInnerSubmit);
-
- return false;
-
- function handleInnerSubmit ( returnedData, textStatus, XMLHttpRequest ) {
- // find form in fake edit page
- var innerform = jQuery("<div>" + returnedData + "</div>").find("form");
-
- // check if we got an error page
- if ( innerform.length === 0 ) {
-
- form.unbind( event );
-
- var iframe = container.find("iframe");
- var doc = iframe[0].contentWindow || iframe[0].contentDocument;
- if (doc.document) {
- doc = doc.document;
- }
-
- doc.open();
- doc.write(returnedData);
- doc.close();
-
- return false;
- }
-
- // Send the form data off, we do not care for the returned data
- var innerformdata = innerform.serialize();
- jQuery.post( innerform.attr("action"), innerformdata );
-
- // build new url for outer page (we have to ask for a purge)
-
- var url = location.href;
-
- // does a querystring exist?
- var start = url.indexOf("action=");
-
- if ( start >= 0 ) {
-
- var stop = url.indexOf("&", start);
-
- if ( stop >= 0 ) {
- url = url.substr( 0, start - 1 ) + url.substr(stop + 1);
- } else {
- url = url.substr( 0, start - 1 );
- }
-
- }
-
- form = jQuery('<form action="' + url + '" method="POST"><input type="hidden" name="action" value="purge"></form>')
- .appendTo('body');
-
- form
- .submit();
-
- fadeOut( container, function(){
- fadeIn( waitIndicator );
- });
-
- return false;
- }
- }
-
- function adjustFrameSize( animate ) {
- // set some inputs
- var oldFrameW = container.width();
- var oldFrameH = container.height();
- var oldContW = content.width();
- var oldContH = content.height();
-
- var availW = Math.floor( jQuery(window).width() * 0.8 );
- var availH = Math.floor( jQuery(window).height() * 0.8 );
-
- var emergencyW = Math.floor( jQuery(window).width() * 0.85 );
- var emergencyH = Math.floor( jQuery(window).height() * 0.85 );
-
- // FIXME: these might not be the true values
- var scrollW = 25;
- var scrollH = 25;
-
-
- // find the dimensions of the document
-
- var body = content.closest('body');
- var html = body.parent();
-
- var scrollTgt = html;
-
- if ( jQuery.browser.webkit || jQuery.browser.safari ) {
- scrollTgt = body;
- }
-
- var scrollTop = scrollTgt.scrollTop();
- var scrollLeft = scrollTgt.scrollLeft();
-
- content
- .css('position', 'absolute')
- .width( 'auto' )
- .height( 'auto' );
-
- // set max dimensions for layout of content
- iframe
- .width( emergencyW )
- .height( emergencyH );
-
- // get dimension values
- var docW = content.width();
- var docH = content.height();
-
- // set old dimensions for layout of content
- iframe
- .width( '100%' )
- .height( '100%' );
-
- content
- .css('position', 'relative')
- .width( oldContW )
- .height( oldContH );
-
- if ( jQuery.browser.msie ) {
- docW += 20;
- docH += 20;
- }
-
- var docpW = docW + 2 * padding;
- var docpH = docH + 2 * padding;
-
- // Flags
-
- var needsHScroll = docpW > emergencyW || ( docpW > emergencyW - scrollW && docpH > emergencyH );
- var needsVScroll = docpH > emergencyH || ( docpH > emergencyH - scrollH && docpW > emergencyW );
-
- var needsWStretch =
- ( docpW > availW && docpW <= emergencyW ) && ( docpH <= emergencyH ) ||
- ( docpW > availW - scrollW && docpW <= emergencyW - scrollW ) && ( docpH > emergencyH );
-
- var needsHStretch =
- ( docpH > availH && docpH <= emergencyH ) && ( docpW <= emergencyW ) ||
- ( docpH > availH - scrollH && docpH <= emergencyH - scrollH ) && ( docpW > emergencyW );
-
- // Outputs
-
- var frameW;
- var frameH;
-
- var contW;
- var contH;
-
- if ( needsWStretch ) {
- contW = docW;
- frameW = docpW;
- } else if ( docpW > availW ) { // form does not even fit with stretching
- contW = docW;
- frameW = availW;
- } else {
- //contW = Math.max( Math.min( 1.5 * docW, availW ), availW / 2 );
- contW = docW;
- frameW = docpW;
- }
-
- if ( needsVScroll ){
- frameW += scrollW;
- } else {
- scrollTop = 0;
- }
-
- if ( needsHStretch ) {
- contH = docH;
- frameH = docpH;
- } else if ( docpH > availH ) { // form does not even fit with stretching
- contH = docH;
- frameH = availH;
- } else {
- //contH = Math.min( 1.1 * docH, availH);
- contH = docH;
- frameH = docpH;
- }
-
- if ( needsHScroll ){
- frameH += scrollH;
- } else {
- scrollLeft = 0;
- }
-
- if ( frameW != oldFrameW || frameH != oldFrameH ) {
-
- if ( jQuery.browser.safari ) {
- html[0].style.overflow="hidden";
- } else {
- iframe[0].style.overflow="hidden";
- }
-
- if ( animate ) {
- content
- .width ( 'auto' )
- .height ( 'auto' );
-
- container.animate({
- width: frameW,
- height: frameH,
- top: Math.floor(( - frameH ) / 2),
- left: Math.floor(( - frameW ) / 2)
- }, {
- duration: 500,
- complete: function() {
-
- if ( jQuery.browser.safari ) {
- html[0].style.overflow="visible";
- } else if ( jQuery.browser.msie ) {
- iframe[0].style.overflow="auto";
- } else {
- iframe[0].style.overflow="visible";
- }
-
- if ( jQuery.browser.mozilla ) {
- content
- .width ( contW )
- .height ( contH );
- } else {
- content
- .width ( 'auto' )
- .height ( 'auto' );
- }
- }
- });
-
- } else {
- container
- .width( frameW )
- .height ( frameH );
-
- container[0].style.top = (Math.floor(( - frameH ) / 2)) + "px";
- container[0].style.left = (Math.floor(( - frameW ) / 2)) + "px";
-
-
- setTimeout(function(){
-
- if ( jQuery.browser.safari ) {
- html[0].style.overflow="visible";
- } else if ( jQuery.browser.msie ) {
- iframe[0].style.overflow="auto";
- } else {
- iframe[0].style.overflow="visible";
- }
-
- }, 100);
-
- if ( jQuery.browser.mozilla ) {
- content
- .width ( contW )
- .height ( contH );
- } else {
- content
- .width ( 'auto' )
- .height ( 'auto' );
- }
-
- }
- } else {
- content
- .width ( 'auto' )
- .height ( 'auto' );
-
- if ( jQuery.browser.safari ) { // Google chrome needs a kick
-
- // turn scrollbars off and on again to really only show them when needed
- html[0].style.overflow="hidden";
-
- setTimeout(function(){
- html[0].style.overflow="visible";
- }, 1);
- }
- }
-
- scrollTgt
- .css('overflow', 'auto')
- .scrollTop(Math.min(scrollTop, docpH - frameH))
- .scrollLeft(scrollLeft);
-
- if ( jQuery.browser.mozilla ) {
- body
- .css('overflow', 'auto');
- }
-
- return true;
- }
-
- function closeFrameAndFollowLink( link ){
- clearTimeout(timer);
-
- fadeOut( container, function(){
- fadeIn ( waitIndicator );
- window.location.href = link;
- });
- }
-
- function handleCloseFrame( event ){
- jQuery(window).unbind( "resize", adjustFrameSize );
- clearTimeout(timer);
-
- fadeOut( container, function(){
- background.fadeOut( function(){
- wrapper.remove();
- });
- });
- return false;
- }
-
- // Saw it on http://robertnyman.com/2006/04/24/get-the-rendered-style-of-an-element
- // and liked it
- function getStyle(oElm, strCssRule){
- var strValue = "";
- if(document.defaultView && document.defaultView.getComputedStyle){
- strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
- }
- else if(oElm.currentStyle){
- strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
- return p1.toUpperCase();
- });
- strValue = oElm.currentStyle[strCssRule];
- }
- return strValue;
- }
-
- function fadeIn(elem, callback ) {
- // no fading for broken browsers
- if ( brokenBrowser ){
-
- elem.show();
- if ( callback ) {
- callback();
- }
- } else {
- // what an ugly hack
- if ( elem === waitIndicator ) {
- elem.fadeIn( 200, callback );
- } else {
- elem.fadeIn( callback );
- }
- }
- }
-
- function fadeOut(elem, callback ) {
- // no fading for broken browsers
- if ( brokenBrowser ){
- elem.hide();
- if ( callback ) {
- callback();
- }
- } else {
- // what an ugly hack
- if ( elem === waitIndicator ) {
- elem.fadeOut( 200, callback );
- } else {
- elem.fadeOut( callback );
- }
- }
- }
-
- function fadeTo(elem, time, target, callback) {
- // no fading for broken browsers
- if ( brokenBrowser ){
-
- if (target > 0) {
- elem[0].style.visibility = "visible";
- } else {
- elem[0].style.visibility = "hidden";
- }
-
- if ( callback ) {
- callback();
- }
-
- } else {
- elem.fadeTo(time, target, callback);
- }
- }
-
- // export public funcitons
- this.handlePopupFormInput = handlePopupFormInput;
- this.handlePopupFormLink = handlePopupFormLink;
- this.adjustFrameSize = adjustFrameSize;
-}(); \ No newline at end of file
diff --git a/SemanticForms/libs/SF_preview.js b/SemanticForms/libs/SF_preview.js
deleted file mode 100644
index 0d4f93b7..00000000
--- a/SemanticForms/libs/SF_preview.js
+++ /dev/null
@@ -1,213 +0,0 @@
-/**
- * Handles dynamic Page Preview for Semantic Forms.
- *
- * @author Stephan Gambke
- */
-
-/*global validateAll */
-
-( function ( $, mw ) {
-
- 'use strict';
-
- var form;
- var previewpane;
- var previewHeight;
-
- /**
- * Called when the content is loaded into the preview pane
- */
- var loadFrameHandler = function handleLoadFrame() {
-
- var iframe = $( this );
- var iframecontents = iframe.contents();
-
- // find div containing the preview
- var content = iframecontents.find( '#wikiPreview' );
-
- var iframebody = content.closest( 'body' );
- var iframedoc = iframebody.parent();
- iframedoc.height( 'auto' );
-
- // this is not a normal MW page (or it uses an unknown skin)
- if ( content.length === 0 ) {
- content = iframebody;
- }
-
- content.parentsUntil( 'html' ).andSelf()
- .css( {
- margin: 0,
- padding: 0,
- width: '100%',
- height: 'auto',
- minWidth: '0px',
- minHeight: '0px',
- 'float': 'none', // Cavendish skin uses floating -> unfloat content
- border: 'none',
- background: 'transparent'
- } )
- .siblings()
- .hide(); // FIXME: Some JS scripts don't like working on hidden elements
-
- // and attach event handler to adjust frame size every time the window
- // size changes
- $( window ).resize( function () {
- iframe.height( iframedoc.height() );
- } );
-
- previewpane.show();
-
- var newPreviewHeight = iframedoc.height();
-
- iframe.height( newPreviewHeight );
-
- $( 'html, body' )
- .scrollTop( $( 'html, body' ).scrollTop() + newPreviewHeight - previewHeight )
- .animate( {
- scrollTop: previewpane.offset().top
- }, 1000 );
-
- previewHeight = newPreviewHeight;
-
- return false;
- };
-
- /**
- * Called when the server has sent the preview
- */
- var resultReceivedHandler = function handleResultReceived( result ) {
-
- var htm = result.result;
-
- var iframe = previewpane.children();
-
- if ( iframe.length === 0 ) {
-
- // set initial height of preview area
- previewHeight = 0;
-
- iframe = $( '<iframe>' )
- .css( { //FIXME: Should this go in a style file?
- 'width': '100%',
- 'height': previewHeight,
- 'border': 'none',
- 'overflow': 'hidden'
- } )
- .load( loadFrameHandler )
- .appendTo( previewpane );
-
- }
-
- var ifr = iframe[0];
- var doc = ifr.contentDocument || ifr.contentWindow.document || ifr.Document;
-
- doc.open();
- doc.write( htm );
- doc.close();
-
- };
-
- /**
- * Called when the preview button was clicked
- */
- var previewButtonClickedHandler = function handlePreviewButtonClicked() {
-
- if ( !validateAll() ) {
- return;
- }
-
- // data array to be sent to the server
- var data = {
- action: 'sfautoedit',
- format: 'json'
- };
-
- // do we have a URL like .../index.php?title=pagename&action=formedit ?
- if ( mw.config.get( 'wgAction' ) === 'formedit' ) {
-
- // set the title, server has to find a suitable form
- data.target = mw.config.get( 'wgPageName' );
-
- // do we have a URL like .../Special:FormEdit/formname/pagename ?
- } else if ( mw.config.get( 'wgCanonicalNamespace' ) === 'Special' && mw.config.get( 'wgCanonicalSpecialPageName' ) === 'FormEdit' ) {
-
- // get the pagename and split it into parts
- var pageName = mw.config.get( 'wgPageName' );
- var parts = pageName.split( '/', 3 );
-
- if ( parts.length > 1 ) { // found a formname
- data.form = parts[1];
- }
-
- if ( parts.length > 2 ) { // found a pagename
- data.target = parts[2];
- }
- }
-
- // add form values to the data
- data.query = form.serialize();
-
- if ( data.query.length > 0 ) {
- data.query += '&';
- }
-
- data.query += 'wpPreview=' + encodeURIComponent( $( this ).attr( 'value' ) );
-
- $.ajax( {
-
- type: 'POST', // request type ( GET or POST )
- url: mw.util.wikiScript( 'api' ), // URL to which the request is sent
- data: data, // data to be sent to the server
- dataType: 'json', // type of data expected back from the server
- success: resultReceivedHandler // function to be called if the request succeeds
- } );
- };
-
- /**
- * Register plugin
- */
- $.fn.sfAjaxPreview = function () {
-
- form = this.closest( 'form' );
- previewpane = $( '#wikiPreview' );
-
- // do some sanity checks
- if ( previewpane.length === 0 || // no ajax preview without preview area
- previewpane.contents().length > 0 || // preview only on an empty previewpane
- form.length === 0 ) { // no ajax preview without form
-
- return this;
- }
-
- // IE does not allow setting of the 'type' attribute for inputs
- // => completely replace the original preview button
- var btn = $( '<input type=\'button\' />' ).insertBefore( this );
-
- this.remove();
-
- // copy all explicitly specified attributes (except 'type' attribute)
- // from the old to the new button
- var oldBtnElement = this[0];
- var i;
-
- for ( i = 0; i < oldBtnElement.attributes.length; i = i + 1 ) {
- var attribute = oldBtnElement.attributes[i];
- if ( attribute.name !== 'type' ) {
- btn.attr( attribute.name, attribute.value );
- }
- }
-
- // register event handler
- btn.click( previewButtonClickedHandler );
-
- return btn;
- };
-
- $( document ).ready( function () {
- if ( mw.config.get( 'wgAction' ) === 'formedit' ||
- mw.config.get( 'wgCanonicalSpecialPageName' ) === 'FormEdit' ) {
- $( '#wpPreview' ).sfAjaxPreview();
- }
- } );
-
-}( jQuery, mediaWiki ) );
diff --git a/SemanticForms/libs/SF_submit.js b/SemanticForms/libs/SF_submit.js
deleted file mode 100644
index 9a3dcdba..00000000
--- a/SemanticForms/libs/SF_submit.js
+++ /dev/null
@@ -1,197 +0,0 @@
-/**
-* Javascript handler for the save-and-continue button
-*
- * @author Stephan Gambke
-*/
-
-/*global validateAll */
-
-( function ( $, mw ) {
-
- 'use strict';
-
- var sacButtons;
- var form;
-
- function setChanged( event ) {
- sacButtons
- .removeAttr( 'disabled' )
- .addClass( 'sf-save_and_continue-changed' );
-
- return true;
- }
-
- /**
- * Called when the server has sent the preview
- */
- var resultReceivedHandler = function handleResultReceived( result, textStatus, jqXHR ) {
-
- // Store the target name
- var target = form.find( 'input[name="target"]' );
-
- if ( target.length === 0 ) {
- target = $( '<input type="hidden" name="target">' );
- form.append ( target );
- }
-
- target.attr( 'value', result.target );
-
- // Store the form name
- target = form.find( 'input[name="form"]' );
-
- if ( target.length === 0 ) {
- target = $( '<input type="hidden" name="form">' );
- form.append ( target );
- }
-
- target.attr( 'value', result.form.title );
-
- sacButtons
- .addClass( 'sf-save_and_continue-ok' )
- .removeClass( 'sf-save_and_continue-wait' )
- .removeClass( 'sf-save_and_continue-error' );
-
- };
-
- var resultReceivedErrorHandler = function handleError( jqXHR ){
-
- var errors = $.parseJSON( jqXHR.responseText ).errors;
-
- sacButtons
- .addClass( 'sf-save_and_continue-error' )
- .removeClass( 'sf-save_and_continue-wait' );
-
- // Remove all old error messages and set new ones
- $( '.errorbox' ).remove();
-
-
- if ( errors.length > 0 ){
- var i;
- for ( i = 0; i < errors.length; i += 1 ) {
- if ( errors[i].level < 2 ) { // show errors and warnings
- $( '#contentSub' )
- .append( '<div id="form_error_header" class="errorbox" style="font-size: medium"><img src="' + mw.config.get( 'sfgScriptPath' ) + '/skins/MW-Icon-AlertMark.png" />&nbsp;' + errors[i].message + '</div><br clear="both" />' );
- }
- }
-
- $( 'html, body' ).scrollTop( $( '#contentSub' ).offset().top );
- }
- };
-
- function collectData( form ) {
- var summaryfield = jQuery( '#wpSummary', form );
- var saveAndContinueSummary = mw.msg( 'sf_formedit_saveandcontinue_summary', mw.msg( 'sf_formedit_saveandcontinueediting' ) );
- var params;
-
- if ( summaryfield.length > 0 ) {
-
- var oldsummary = summaryfield.attr( 'value' );
-
- if ( oldsummary !== '' ) {
- summaryfield.attr( 'value', oldsummary + ' (' + saveAndContinueSummary + ')' );
- } else {
- summaryfield.attr( 'value', saveAndContinueSummary );
- }
-
- params = form.serialize();
-
- summaryfield.attr( 'value', oldsummary );
- } else {
- params = form.serialize();
- params += '&wpSummary=' + saveAndContinueSummary;
- }
-
- if ( mw.config.get( 'wgAction' ) === 'formedit' ) {
- params += '&target=' + encodeURIComponent( mw.config.get( 'wgPageName' ) );
- } else if ( mw.config.get( 'wgCanonicalSpecialPageName' ) === 'FormEdit' ) {
- var url = mw.config.get( 'wgPageName' );
-
- var start = url.indexOf( '/' ) + 1; // find start of subpage
- var stop;
-
- if ( start >= 0 ) {
- stop = url.indexOf( '/', start ); // find end of first subpage
- } else {
- stop = -1;
- }
-
- if ( stop >= 0 ) {
- params += '&form=' + encodeURIComponent( url.substring( start, stop ) );
-
- start = stop + 1;
- params += '&target=' + encodeURIComponent( url.substr( start ) );
-
- } else {
- params += '&form=' + encodeURIComponent( url.substr( start ) );
- }
- }
-
- params += '&wpMinoredit=1';
-
- return params;
- }
-
- function handleSaveAndContinue( event ) {
-
- event.stopImmediatePropagation();
-
- // remove old error messages
- var el = document.getElementById( 'form_error_header' );
-
- if ( el ) {
- el.parentNode.removeChild( el );
- }
-
- if ( validateAll() ) {
- // disable save and continue button
- sacButtons
- .attr( 'disabled', 'disabled' )
- .addClass( 'sf-save_and_continue-wait' )
- .removeClass( 'sf-save_and_continue-changed' );
-
- var form = $( '#sfForm' );
-
- var data = {
- action: 'sfautoedit',
- format: 'json',
- query: collectData( form ) // add form values to the data
- };
-
- data.query += '&wpSave=' + encodeURIComponent( $( event.currentTarget ).attr( 'value' ) );
-
- $.ajax( {
-
- type: 'POST', // request type ( GET or POST )
- url: mw.util.wikiScript( 'api' ), // URL to which the request is sent
- data: data, // data to be sent to the server
- dataType: 'json', // type of data expected back from the server
- success: resultReceivedHandler, // function to be called if the request succeeds
- error: resultReceivedErrorHandler // function to be called on error
- } );
-
- }
-
- return false;
- }
-
- if ( mw.config.get( 'wgAction' ) === 'formedit' || mw.config.get( 'wgCanonicalSpecialPageName' ) === 'FormEdit' ) {
- form = $( '#sfForm' );
-
- sacButtons = $( '.sf-save_and_continue', form );
- sacButtons.click( handleSaveAndContinue );
-
- $( form )
- .on( 'keyup', 'input,select,textarea', function ( event ) {
- if ( event.which < 32 ){
- return true;
- }
-
- return setChanged( event );
- } )
- .on( 'change', 'input,select,textarea', setChanged )
- .on( 'click', '.multipleTemplateAdder,.removeButton,.rearrangerImage', setChanged )
- .on( 'mousedown', '.rearrangerImage',setChanged );
-
- }
-
-}( jQuery, mediaWiki ) );
diff --git a/SemanticForms/libs/SF_wikieditor.js b/SemanticForms/libs/SF_wikieditor.js
deleted file mode 100644
index 85270810..00000000
--- a/SemanticForms/libs/SF_wikieditor.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// create ext if it does not exist yet
-/*global wgWikiEditorEnabledModules*/
-if ( window.ext == null || typeof( window.ext ) === "undefined" ) {
- window.ext = {};
-}
-
-window.ext.wikieditor = {
- // initialize the wikieditor on the specified element
- init : function init ( input_id, params ) {
- jQuery( function() {
- if ( window.mediaWiki ) {
- var input = jQuery( '#' + input_id );
-
- // load toolbar
- mediaWiki.loader.using( ['jquery.wikiEditor.toolbar', 'jquery.wikiEditor.toolbar.config'] , function(){
- if ( jQuery.wikiEditor.isSupported( jQuery.wikiEditor.modules.toolbar ) ) {
- input.wikiEditor( 'addModule', jQuery.wikiEditor.modules.toolbar.config.getDefaultConfig() );
-
- // hide sig if required
- if ( wgWikiEditorEnabledModules && wgWikiEditorEnabledModules.hidesig === true ) {
- input.wikiEditor( 'removeFromToolbar', {
- 'section': 'main',
- 'group': 'insert',
- 'tool': 'signature'
- } );
- }
-
- }
- });
-
- // load dialogs
- mediaWiki.loader.using( ['jquery.wikiEditor.dialogs', 'jquery.wikiEditor.dialogs.config'] , function(){
- if ( jQuery.wikiEditor.isSupported( jQuery.wikiEditor.modules.dialogs ) ) {
- jQuery.wikiEditor.modules.dialogs.config.replaceIcons( input );
- input.wikiEditor( 'addModule', $.wikiEditor.modules.dialogs.config.getDefaultConfig() );
-
- }
- });
- }
- });
- }
-};
diff --git a/SemanticForms/libs/SemanticForms.js b/SemanticForms/libs/SemanticForms.js
deleted file mode 100644
index 49e07ae7..00000000
--- a/SemanticForms/libs/SemanticForms.js
+++ /dev/null
@@ -1,1084 +0,0 @@
-/**
- * SemanticForms.js
- *
- * Javascript utility functions for the Semantic Forms extension.
- *
- * @author Yaron Koren
- * @author Sanyam Goyal
- * @author Stephan Gambke
- * @author Jeffrey Stuckman
- * @author Harold Solbrig
- * @author Eugene Mednikov
- */
- /*global sfgShowOnSelect, sfgFieldProperties, validateAll, alert, sf*/
-
-// Activate autocomplete functionality for the specified field
-(function(jQuery) {
-
- /* extending jQuery functions for custom highlighting */
- jQuery.ui.autocomplete.prototype._renderItem = function( ul, item) {
-
- var delim = this.element.context.delimiter;
- var term;
- if ( delim === null ) {
- term = this.term;
- } else {
- term = this.term.split( delim ).pop();
- }
- var re = new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi");
- var loc = item.label.search(re);
- var t;
- if (loc >= 0) {
- t = item.label.substr(0, loc) + '<strong>' + item.label.substr(loc, term.length) + '</strong>' + item.label.substr(loc + term.length);
- } else {
- t = item.label;
- }
- return jQuery( "<li></li>" )
- .data( "item.autocomplete", item )
- .append( " <a>" + t + "</a>" )
- .appendTo( ul );
- };
-
- jQuery.fn.attachAutocomplete = function() {
- return this.each(function() {
- // Get all the necessary values from the input's "autocompletesettings"
- // attribute. This should probably be done as three separate attributes,
- // instead.
- var field_string = jQuery(this).attr("autocompletesettings");
-
- if ( typeof field_string === 'undefined' ) {
- return;
- }
-
- var field_values = field_string.split(',');
- var delimiter = null;
- var data_source = field_values[0];
- if (field_values[1] == 'list') {
- delimiter = ",";
- if (field_values[2] !== null && field_values[2] !== undefined) {
- delimiter = field_values[2];
- }
- }
-
- // Modify the delimiter. If it's "\n", change it to an actual
- // newline - otherwise, add a space to the end.
- // This doesn't cover the case of a delimiter that's a newline
- // plus something else, like ".\n" or "\n\n", but as far as we
- // know no one has yet needed that.
- if ( delimiter !== null && delimiter !== undefined ) {
- if ( delimiter == "\\n" ) {
- delimiter = "\n";
- } else {
- delimiter += " ";
- }
- }
- // Store this value within the object, so that it can be used
- // during highlighting of the search term as well.
- this.delimiter = delimiter;
-
- /* extending jquery functions */
- jQuery.extend( jQuery.ui.autocomplete, {
- filter: function(array, term) {
- var sfgAutocompleteOnAllChars = mw.config.get( 'sfgAutocompleteOnAllChars' );
- var matcher;
- if ( sfgAutocompleteOnAllChars ) {
- matcher = new RegExp(jQuery.ui.autocomplete.escapeRegex(term), "i" );
- } else {
- matcher = new RegExp("\\b" + jQuery.ui.autocomplete.escapeRegex(term), "i" );
- }
- return jQuery.grep( array, function(value) {
- return matcher.test( value.label || value.value || value );
- });
- }
- });
-
- var values = jQuery(this).data('autocompletevalues');
- if ( !values ) {
- var sfgAutocompleteValues = mw.config.get( 'sfgAutocompleteValues' );
- values = sfgAutocompleteValues[field_string];
- }
- var split = function (val) {
- return val.split(delimiter);
- };
- var extractLast = function (term) {
- return split(term).pop();
- };
- if (values !== null && values !== undefined) {
- // Local autocompletion
-
- if (delimiter !== null && delimiter !== undefined) {
- // Autocomplete for multiple values
-
- var thisInput = jQuery(this);
-
- jQuery(this).autocomplete({
- minLength: 0,
- source: function(request, response) {
- // We need to re-get the set of values, since
- // the "values" variable gets overwritten.
- values = thisInput.data( 'autocompletevalues' );
- if ( !values ) {
- values = sfgAutocompleteValues[field_string];
- }
- response(jQuery.ui.autocomplete.filter(values, extractLast(request.term)));
- },
- focus: function() {
- // prevent value inserted on focus
- return false;
- },
- select: function(event, ui) {
- var terms = split( this.value );
- // remove the current input
- terms.pop();
- // add the selected item
- terms.push( ui.item.value );
- // add placeholder to get the comma-and-space at the end
- terms.push("");
- this.value = terms.join(delimiter);
- return false;
- }
- });
-
- } else {
- // Autocomplete for a single value
- jQuery(this).autocomplete({
- source:values
- });
- }
- } else {
- // Remote autocompletion.
- var myServer = mw.util.wikiScript( 'api' );
- var data_type = jQuery(this).attr("autocompletedatatype");
- myServer += "?action=sfautocomplete&format=json&" + data_type + "=" + data_source;
-
- if (delimiter !== null && delimiter !== undefined) {
- jQuery(this).autocomplete({
- source: function(request, response) {
- jQuery.getJSON(myServer, {
- substr: extractLast(request.term)
- }, function( data ) {
- response(jQuery.map(data.sfautocomplete, function(item) {
- return {
- value: item.title
- };
- }));
- });
- },
- search: function() {
- // custom minLength
- var term = extractLast(this.value);
- if (term.length < 1) {
- return false;
- }
- },
- focus: function() {
- // prevent value inserted on focus
- return false;
- },
- select: function(event, ui) {
- var terms = split( this.value );
- // remove the current input
- terms.pop();
- // add the selected item
- terms.push( ui.item.value );
- // add placeholder to get the comma-and-space at the end
- terms.push("");
- this.value = terms.join(delimiter);
- return false;
- }
- } );
- } else {
- jQuery(this).autocomplete({
- minLength: 1,
- source: function(request, response) {
- jQuery.ajax({
- url: myServer,
- dataType: "json",
- data: {
- substr:request.term
- },
- success: function( data ) {
- response(jQuery.map(data.sfautocomplete, function(item) {
- return {
- value: item.title
- };
- }));
- }
- });
- },
- open: function() {
- jQuery(this).removeClass("ui-corner-all").addClass("ui-corner-top");
- },
- close: function() {
- jQuery(this).removeClass("ui-corner-top").addClass("ui-corner-all");
- }
- } );
- }
- }
- });
- };
-})( jQuery );
-
-
-/*
- * Functions to register/unregister methods for the initialization and
- * validation of inputs.
- */
-
-// Initialize data object to hold initialization and validation data
-function setupSF() {
-
- jQuery("#sfForm").data("SemanticForms",{
- initFunctions : [],
- validationFunctions : []
- });
-
-}
-
-// Register a validation method
-//
-// More than one method may be registered for one input by subsequent calls to
-// SemanticForms_registerInputValidation.
-//
-// Validation functions and their data are stored in a numbered array
-//
-// @param valfunction The validation functions. Must take a string (the input's id) and an object as parameters
-// @param param The parameter object given to the validation function
-jQuery.fn.SemanticForms_registerInputValidation = function(valfunction, param) {
-
- if ( ! this.attr("id") ) {
- return this;
- }
-
- if ( ! jQuery("#sfForm").data("SemanticForms") ) {
- setupSF();
- }
-
- jQuery("#sfForm").data("SemanticForms").validationFunctions.push({
- input : this.attr("id"),
- valfunction : valfunction,
- parameters : param
- });
-
- return this;
-};
-
-// Register an initialization method
-//
-// More than one method may be registered for one input by subsequent calls to
-// SemanticForms_registerInputInit. This method also executes the initFunction
-// if the element referenced by /this/ is not part of a multipleTemplateStarter.
-//
-// Initialization functions and their data are stored in a associative array
-//
-// @param initFunction The initialization function. Must take a string (the input's id) and an object as parameters
-// @param param The parameter object given to the initialization function
-// @param noexecute If set, the initialization method will not be executed here
-jQuery.fn.SemanticForms_registerInputInit = function( initFunction, param, noexecute ) {
-
- // return if element has no id
- if ( ! this.attr("id") ) {
- return this;
- }
-
- // setup data structure if necessary
- if ( ! jQuery("#sfForm").data("SemanticForms") ) {
- setupSF();
- }
-
- // if no initialization function for this input was registered yet,
- // create entry
- if ( ! jQuery("#sfForm").data("SemanticForms").initFunctions[this.attr("id")] ) {
- jQuery("#sfForm").data("SemanticForms").initFunctions[this.attr("id")] = [];
- }
-
- // record initialization function
- jQuery("#sfForm").data("SemanticForms").initFunctions[this.attr("id")].push({
- initFunction : initFunction,
- parameters : param
- });
-
- // execute initialization if input is not part of multipleTemplateStarter
- // and if not forbidden
- if ( this.closest(".multipleTemplateStarter").length === 0 && !noexecute) {
- var input = this;
- // ensure initFunction is only exectued after doc structure is complete
- jQuery(function() {initFunction ( input.attr("id"), param );});
- }
-
- return this;
-};
-
-// Unregister all validation methods for the element referenced by /this/
-jQuery.fn.SemanticForms_unregisterInputValidation = function() {
-
- var sfdata = jQuery("#sfForm").data("SemanticForms");
-
- if ( this.attr("id") && sfdata ) {
- // delete every validation method for this input
- for ( var i = 0; i < sfdata.validationFunctions.length; i++ ) {
- if ( typeof sfdata.validationFunctions[i] !== 'undefined' &&
- sfdata.validationFunctions[i].input == this.attr("id") ) {
- delete sfdata.validationFunctions[i];
- }
- }
- }
-
- return this;
-};
-
-// Unregister all initialization methods for the element referenced by /this/
-jQuery.fn.SemanticForms_unregisterInputInit = function() {
-
- if ( this.attr("id") && jQuery("#sfForm").data("SemanticForms") ) {
- delete jQuery("#sfForm").data("SemanticForms").initFunctions[this.attr("id")];
- }
-
- return this;
-};
-
-/*
- * Functions for handling 'show on select'
- */
-
-// Display a div that would otherwise be hidden by "show on select".
-function showDiv(div_id, instanceWrapperDiv, speed) {
- var elem = jQuery('[id="' + div_id + '"]', instanceWrapperDiv);
-
- elem
- .find(".hiddenBySF")
- .removeClass('hiddenBySF')
-
- .find(".disabledBySF")
- .removeAttr('disabled')
- .removeClass('disabledBySF');
-
- elem.each( function() {
- if ( jQuery(this).css('display') == 'none' ) {
-
- jQuery(this).slideDown(speed, function() {
- jQuery(this).fadeTo(speed,1);
- });
-
- }
- });
-}
-
-// Hide a div due to "show on select". The CSS class is there so that SF can
-// ignore the div's contents when the form is submitted.
-function hideDiv(div_id, instanceWrapperDiv, speed) {
- // IDs can't contain spaces, and jQuery won't work with such IDs - if
- // this one has a space, display an alert.
- if ( div_id.indexOf( ' ' ) > -1 ) {
- // TODO - this should probably be a language value, instead of
- // hardcoded in English.
- alert( "Warning: this form has \"show on select\" pointing to an invalid element ID (\"" + div_id + "\") - IDs in HTML cannot contain spaces." );
- }
-
- var elem = jQuery('[id="' + div_id + '"]', instanceWrapperDiv);
- elem.find("span, div").addClass('hiddenBySF');
-
- elem.each( function() {
- if ( jQuery(this).css('display') != 'none' ) {
-
- // if 'display' is not 'hidden', but the element is hidden otherwise
- // (e.g. by having height = 0), just hide it, else animate the hiding
- if ( jQuery(this).is(':hidden') ) {
- jQuery(this).hide();
- } else {
- jQuery(this).fadeTo(speed, 0, function() {
- jQuery(this).slideUp(speed);
- });
- }
- }
- });
-}
-
-// Show this div if the current value is any of the relevant options -
-// otherwise, hide it.
-function showDivIfSelected(options, div_id, inputVal, instanceWrapperDiv, initPage) {
- for ( var i = 0; i < options.length; i++ ) {
- // If it's a listbox and the user has selected more than one
- // value, it'll be an array - handle either case.
- if ((jQuery.isArray(inputVal) && jQuery.inArray(options[i], inputVal) >= 0) ||
- (!jQuery.isArray(inputVal) && (inputVal == options[i]))) {
- showDiv( div_id, instanceWrapperDiv, initPage ? 0 : 'fast' );
- return;
- }
- }
- hideDiv(div_id, instanceWrapperDiv, initPage ? 0 : 'fast' );
-}
-
-// Used for handling 'show on select' for the 'dropdown' and 'listbox' inputs.
-jQuery.fn.showIfSelected = function(initPage) {
- var inputVal = this.val();
- var sfgShowOnSelect = mw.config.get( 'sfgShowOnSelect' );
- var showOnSelectVals = sfgShowOnSelect[this.attr("id")];
-
- var instanceWrapperDiv = this.closest('.multipleTemplateInstance');
- if ( instanceWrapperDiv.length === 0 ) {
- instanceWrapperDiv = null;
- }
-
- if ( showOnSelectVals !== undefined ) {
- for ( var i = 0; i < showOnSelectVals.length; i++ ) {
- var options = showOnSelectVals[i][0];
- var div_id = showOnSelectVals[i][1];
- showDivIfSelected( options, div_id, inputVal, instanceWrapperDiv, initPage );
- }
- }
-
- return this;
-};
-
-// Show this div if any of the relevant selections are checked -
-// otherwise, hide it.
-jQuery.fn.showDivIfChecked = function(options, div_id, instanceWrapperDiv, initPage ) {
- for ( var i = 0; i < options.length; i++ ) {
- if (jQuery(this).find('[value="' + options[i] + '"]').is(":checked")) {
- showDiv(div_id, instanceWrapperDiv, initPage ? 0 : 'fast' );
- return this;
- }
- }
- hideDiv(div_id, instanceWrapperDiv, initPage ? 0 : 'fast' );
-
- return this;
-};
-
-// Used for handling 'show on select' for the 'checkboxes' and 'radiobutton'
-// inputs.
-jQuery.fn.showIfChecked = function(initPage) {
- var sfgShowOnSelect = mw.config.get( 'sfgShowOnSelect' );
- var showOnSelectVals = sfgShowOnSelect[this.attr("id")];
-
- var instanceWrapperDiv = this.closest('.multipleTemplateInstance');
- if ( instanceWrapperDiv.length === 0 ) {
- instanceWrapperDiv = null;
- }
-
- if ( showOnSelectVals !== undefined ) {
- for ( var i = 0; i < showOnSelectVals.length; i++ ) {
- var options = showOnSelectVals[i][0];
- var div_id = showOnSelectVals[i][1];
- this.showDivIfChecked(options, div_id, instanceWrapperDiv, initPage );
- }
- }
-
- return this;
-};
-
-// Used for handling 'show on select' for the 'checkbox' input.
-jQuery.fn.showIfCheckedCheckbox = function(initPage) {
- var sfgShowOnSelect = mw.config.get( 'sfgShowOnSelect' );
- var div_id = sfgShowOnSelect[this.attr("id")];
-
- var instanceWrapperDiv = this.closest('.multipleTemplateInstance');
- if ( instanceWrapperDiv.length === 0 ) {
- instanceWrapperDiv = null;
- }
-
- if (jQuery(this).is(":checked")) {
- showDiv(div_id, instanceWrapperDiv, initPage ? 0 : 'fast' );
- } else {
- hideDiv(div_id, instanceWrapperDiv, initPage ? 0 : 'fast' );
- }
-
- return this;
-};
-
-/*
- * Validation functions
- */
-
-// Display an error message on the end of an input.
-jQuery.fn.addErrorMessage = function(msg, val) {
- this.append(' ').append( $('<span>').addClass( 'errorMessage' ).text( mw.msg( msg, val ) ) );
-};
-
-jQuery.fn.validateNumInstances = function() {
- var minimumInstances = this.attr("minimumInstances");
- var maximumInstances = this.attr("maximumInstances");
- var numInstances = this.find("div.multipleTemplateInstance").length;
- if ( numInstances < minimumInstances ) {
- this.parent().addErrorMessage( 'sf_too_few_instances_error', minimumInstances );
- return false;
- } else if ( numInstances > maximumInstances ) {
- this.parent().addErrorMessage( 'sf_too_many_instances_error', maximumInstances );
- return false;
- } else {
- return true;
- }
-};
-
-jQuery.fn.validateMandatoryField = function() {
- var fieldVal = this.find(".mandatoryField").val();
- var isEmpty;
- if (fieldVal === null) {
- isEmpty = true;
- } else if (jQuery.isArray(fieldVal)) {
- isEmpty = (fieldVal.length === 0);
- } else {
- isEmpty = (fieldVal.replace(/\s+/, '') === '');
- }
- if (isEmpty) {
- this.addErrorMessage( 'sf_blank_error' );
- return false;
- } else {
- return true;
- }
-};
-
-jQuery.fn.validateMandatoryComboBox = function() {
- var combobox = this.find( "input.sfComboBox" );
- if (combobox.val() === '') {
- this.addErrorMessage( 'sf_blank_error' );
- return false;
- } else {
- return true;
- }
-};
-
-jQuery.fn.validateMandatoryDateField = function() {
- if (this.find(".dayInput").val() === '' ||
- this.find(".monthInput").val() === '' ||
- this.find(".yearInput").val() === '') {
- this.addErrorMessage( 'sf_blank_error' );
- return false;
- } else {
- return true;
- }
-};
-
-// Special handling for radiobuttons, because what's being checked
-// is the first radiobutton, which has an empty value.
-jQuery.fn.validateMandatoryRadioButton = function() {
- if (this.find("[value='']").is(':checked')) {
- this.addErrorMessage( 'sf_blank_error' );
- return false;
- } else {
- return true;
- }
-};
-
-jQuery.fn.validateMandatoryCheckboxes = function() {
- // Get the number of checked checkboxes within this span - must
- // be at least one.
- var numChecked = this.find("input:checked").size();
- if (numChecked === 0) {
- this.addErrorMessage( 'sf_blank_error' );
- return false;
- } else {
- return true;
- }
-};
-
-/*
- * Type-based validation
- */
-
-jQuery.fn.validateURLField = function() {
- var fieldVal = this.find("input").val();
- // code borrowed from http://snippets.dzone.com/posts/show/452
- var url_regexp = /(ftp|http|https|rtsp|news):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
- if (fieldVal === "" || url_regexp.test(fieldVal)) {
- return true;
- } else {
- this.addErrorMessage( 'sf_bad_url_error' );
- return false;
- }
-};
-
-jQuery.fn.validateEmailField = function() {
- var fieldVal = this.find("input").val();
- // code borrowed from http://javascript.internet.com/forms/email-validation---basic.html
- var email_regexp = /^\s*\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,6})+\s*$/;
- if (fieldVal === '' || email_regexp.test(fieldVal)) {
- return true;
- } else {
- this.addErrorMessage( 'sf_bad_email_error' );
- return false;
- }
-};
-
-jQuery.fn.validateNumberField = function() {
- var fieldVal = this.find("input").val();
- // Handle "E notation"/scientific notation ("1.2e-3") in addition
- // to regular numbers
- if (fieldVal === '' ||
- fieldVal.match(/^\s*[\-+]?((\d+[\.,]?\d*)|(\d*[\.,]?\d+))([eE]?[\-\+]?\d+)?\s*$/)) {
- return true;
- } else {
- this.addErrorMessage( 'sf_bad_number_error' );
- return false;
- }
-};
-
-jQuery.fn.validateDateField = function() {
- // validate only if day and year fields are both filled in
- var dayVal = this.find(".dayInput").val();
- var yearVal = this.find(".yearInput").val();
- if (dayVal === '' || yearVal === '') {
- return true;
- } else if (dayVal.match(/^\d+$/) && dayVal <= 31) {
- // no year validation, since it can also include
- // 'BC' and possibly other non-number strings
- return true;
- } else {
- this.addErrorMessage( 'sf_bad_date_error' );
- return false;
- }
-};
-
-window.validateAll = function () {
- var num_errors = 0;
-
- // Remove all old error messages.
- jQuery(".errorMessage").remove();
-
- // Make sure all inputs are ignored in the "starter" instance
- // of any multiple-instance template.
- jQuery(".multipleTemplateStarter").find("span, div").addClass("hiddenBySF");
-
- jQuery(".multipleTemplateList").each( function() {
- if (! jQuery(this).validateNumInstances() ) {
- num_errors += 1;
- }
- });
-
- jQuery("span.inputSpan.mandatoryFieldSpan").not(".hiddenBySF").each( function() {
- if (! jQuery(this).validateMandatoryField() ) {
- num_errors += 1;
- }
- });
- jQuery("div.ui-widget.mandatory").not(".hiddenBySF").each( function() {
- if (! jQuery(this).validateMandatoryComboBox() ) {
- num_errors += 1;
- }
- });
- jQuery("span.dateInput.mandatoryFieldSpan").not(".hiddenBySF").each( function() {
- if (! jQuery(this).validateMandatoryDateField() ) {
- num_errors += 1;
- }
- });
- jQuery("span.radioButtonSpan.mandatoryFieldSpan").not(".hiddenBySF").each( function() {
- if (! jQuery(this).validateMandatoryRadioButton() ) {
- num_errors += 1;
- }
- });
- jQuery("span.checkboxesSpan.mandatoryFieldSpan").not(".hiddenBySF").each( function() {
- if (! jQuery(this).validateMandatoryCheckboxes() ) {
- num_errors += 1;
- }
- });
- jQuery("span.URLInput").not(".hiddenBySF").each( function() {
- if (! jQuery(this).validateURLField() ) {
- num_errors += 1;
- }
- });
- jQuery("span.emailInput").not(".hiddenBySF").each( function() {
- if (! jQuery(this).validateEmailField() ) {
- num_errors += 1;
- }
- });
- jQuery("span.numberInput").not(".hiddenBySF").each( function() {
- if (! jQuery(this).validateNumberField() ) {
- num_errors += 1;
- }
- });
- jQuery("span.dateInput").not(".hiddenBySF").each( function() {
- if (! jQuery(this).validateDateField() ) {
- num_errors += 1;
- }
- });
-
- // call registered validation functions
- var sfdata = jQuery("#sfForm").data('SemanticForms');
-
- if ( sfdata && sfdata.validationFunctions.length > 0 ) { // found data object?
-
- // for every registered input
- for ( var i = 0; i < sfdata.validationFunctions.length; i++ ) {
-
- // if input is not part of multipleTemplateStarter
- if ( typeof sfdata.validationFunctions[i] !== 'undefined' &&
- jQuery("#" + sfdata.validationFunctions[i].input).closest(".multipleTemplateStarter").length === 0 &&
- jQuery("#" + sfdata.validationFunctions[i].input).closest(".hiddenBySF").length === 0 ) {
-
- if (! sfdata.validationFunctions[i].valfunction(
- sfdata.validationFunctions[i].input,
- sfdata.validationFunctions[i].parameters)
- ) {
- num_errors += 1;
- }
- }
- }
- }
-
- if (num_errors > 0) {
- // add error header, if it's not there already
- if (jQuery("#form_error_header").size() === 0) {
- jQuery("#contentSub").append('<div id="form_error_header" class="errorbox" style="font-size: medium"><img src="' + mw.config.get( 'sfgScriptPath' ) + '/skins/MW-Icon-AlertMark.png" />&nbsp;' + mw.message( 'sf_formerrors_header' ).escaped() + '</div><br clear="both" />');
- }
- scroll(0, 0);
- } else {
- // Disable inputs hidden due to either "show on select" or
- // because they're part of the "starter" div for
- // multiple-instance templates, so that they aren't
- // submitted by the form.
- jQuery('.hiddenBySF').find("input, select, textarea").not(':disabled')
- .attr('disabled', 'disabled')
- .addClass('disabledBySF');
- //remove error box if it exists because there are no errors in the form now
- jQuery("#contentSub").find(".errorbox").remove();
- }
- return (num_errors === 0);
-};
-
-/**
- * Functions for multiple-instance templates.
- */
-
-jQuery.fn.addInstance = function( addAboveCurInstance ) {
- // Global variable.
- num_elements++;
-
- // Create the new instance
- var new_div = this.closest(".multipleTemplateWrapper")
- .find(".multipleTemplateStarter")
- .clone()
- .removeClass('multipleTemplateStarter')
- .addClass('multipleTemplateInstance')
- .addClass('multipleTemplate') // backwards compatibility
- .removeAttr("id")
- .fadeTo(0,0)
- .slideDown('fast', function() {
- jQuery(this).fadeTo('fast', 1);
- });
-
- new_div.find('.hiddenBySF')
- .removeClass('hiddenBySF')
-
- .find('.disabledBySF')
- .removeAttr('disabled')
- .removeClass('disabledBySF');
-
- // Make internal ID unique for the relevant form elements, and replace
- // the [num] index in the element names with an actual unique index
- new_div.find("input, select, textarea").each(
- function() {
- // Add in a 'b' at the end of the name to reduce the
- // chance of name collision with another field
- if (this.name) {
- var old_name = this.name.replace(/\[num\]/g, '');
- jQuery(this).attr('origName', old_name);
- this.name = this.name.replace(/\[num\]/g, '[' + num_elements + 'b]');
- }
-
- if (this.id) {
-
- var old_id = this.id;
-
- this.id = this.id.replace(/input_/g, 'input_' + num_elements + '_');
-
- // TODO: Data in sfgShowOnSelect should probably be stored in
- // jQuery("#sfForm").data('SemanticForms')
- if ( sfgShowOnSelect[ old_id ] ) {
- sfgShowOnSelect[ this.id ] = sfgShowOnSelect[ old_id ];
- }
-
- // register initialization and validation methods for new inputs
-
- var sfdata = jQuery("#sfForm").data('SemanticForms');
- if ( sfdata ) { // found data object?
- var i;
- if ( sfdata.initFunctions[old_id] ) {
-
- // For every initialization method for
- // input with id old_id, register the
- // method for the new input.
- for ( i = 0; i < sfdata.initFunctions[old_id].length; i++ ) {
-
- jQuery(this).SemanticForms_registerInputInit(
- sfdata.initFunctions[old_id][i].initFunction,
- sfdata.initFunctions[old_id][i].parameters,
- true //do not yet execute
- );
- }
- }
-
- // For every validation method for the
- // input with ID old_id, register it
- // for the new input.
- for ( i = 0; i < sfdata.validationFunctions.length; i++ ) {
-
- if ( typeof sfdata.validationFunctions[i] !== 'undefined' &&
- sfdata.validationFunctions[i].input == old_id ) {
-
- jQuery(this).SemanticForms_registerInputValidation(
- sfdata.validationFunctions[i].valfunction,
- sfdata.validationFunctions[i].parameters
- );
- }
- }
- }
- }
- }
- );
-
- new_div.find('a').attr('href', function() {
- return this.href.replace(/input_/g, 'input_' + num_elements + '_');
- });
-
- new_div.find('span').attr('id', function() {
- return this.id.replace(/span_/g, 'span_' + num_elements + '_');
- });
-
- // Add the new instance
- if ( addAboveCurInstance ) {
- new_div.insertBefore(this.closest(".multipleTemplateInstance"));
- } else {
- this.closest(".multipleTemplateWrapper")
- .find(".multipleTemplateList")
- .append(new_div);
- }
-
- new_div.initializeJSElements(true);
-
- // Initialize new inputs
- new_div.find("input, select, textarea").each(
- function() {
-
- if (this.id) {
-
- var sfdata = jQuery("#sfForm").data('SemanticForms');
- if ( sfdata ) {
-
- // have to store data array: the id attribute
- // of 'this' might be changed in the init function
- var thatData = sfdata.initFunctions[this.id] ;
-
- if ( thatData ) { // if anything registered at all
- // Call every initialization method
- // for this input
- for ( var i = 0; i < thatData.length; i++ ) {
- thatData[i].initFunction(
- this.id,
- thatData[i].parameters
- );
- }
- }
- }
- }
- }
- );
-
-};
-
-// The first argument is needed, even though it's an attribute of the element
-// on which this function is called, because it's the 'name' attribute for
-// regular inputs, and the 'origName' attribute for inputs in multiple-instance
-// templates.
-jQuery.fn.setDependentAutocompletion = function( dependentField, baseField, baseValue ) {
- var propName = sfgFieldProperties[dependentField];
- var baseProp = sfgFieldProperties[baseField];
- var myServer = mw.config.get( 'wgScriptPath' ) + "/api.php";
- myServer += "?action=sfautocomplete&format=json&property=" + propName + "&baseprop=" + baseProp + "&basevalue=" + baseValue;
- var dependentValues = [];
- var thisInput = jQuery(this);
- // We use jQuery.ajax() here instead of jQuery.getJSON() so that the
- // 'async' parameter can be set. That, in turn, is set because
- // if the 2nd, "dependent" field is a combo box, it can have weird
- // behavior: clicking on the down arrow for the combo box leads to a
- // "blur" event for the base field, which causes the possible
- // values to get recalculated, but not in time for the dropdown to
- // change values - it still shows the old values. By setting
- // "async: false", we guarantee that old values won't be shown - if
- // the values haven't been recalculated yet, the dropdown won't
- // appear at all.
- // @TODO - handle this the right way, by having special behavior for
- // the dropdown - it should get delayed until the values are
- // calculated, then appear.
- jQuery.ajax({
- url: myServer,
- dataType: 'json',
- async: false,
- success: function(data) {
- var realData = data.sfautocomplete;
- jQuery.each(realData, function(key, val) {
- dependentValues.push(val.title);
- });
- thisInput.data('autocompletevalues', dependentValues);
- thisInput.attachAutocomplete();
- }
- });
-};
-
-/**
- * Called on a 'base' field (e.g., for a country) - sets the autocompletion
- * for its 'dependent' field (e.g., for a city).
- */
-jQuery.fn.setAutocompleteForDependentField = function( partOfMultiple ) {
- var curValue = jQuery(this).val();
- if ( curValue === null ) { return this; }
-
- var nameAttr = partOfMultiple ? 'origName' : 'name';
- var name = jQuery(this).attr(nameAttr);
- var sfgDependentFields = mw.config.get( 'sfgDependentFields' );
- var dependent_on_me = [];
- for ( var i = 0; i < sfgDependentFields.length; i++ ) {
- var dependentFieldPair = sfgDependentFields[i];
- if ( dependentFieldPair[0] == name ) {
- dependent_on_me.push(dependentFieldPair[1]);
- }
- }
- dependent_on_me = jQuery.unique(dependent_on_me);
-
- var self = this;
- jQuery.each( dependent_on_me, function() {
- var dependentField = this;
- var dependent_field_element;
- if ( partOfMultiple ) {
- dependent_field_element = jQuery(self).closest(".multipleTemplateInstance")
- .find('[origName="' + dependentField + '"]');
- } else {
- dependent_field_element = jQuery('[name="' + dependentField + '"]');
- }
- var class_name = $(dependent_field_element).attr( 'class' );
- if ( class_name.indexOf( 'sfComboBox' ) != -1 ) {
- var cmbox = new sf.select2.combobox();
- cmbox.refresh(dependent_field_element);
- } else if ( class_name.indexOf( 'sfTokens' ) != -1 ) {
- var tokens = new sf.select2.tokens();
- tokens.refresh(dependent_field_element);
- } else {
- dependent_field_element.setDependentAutocompletion(dependentField, name, curValue);
- }
- });
-
-
- return this;
-};
-
-/**
- * Initialize all the JS-using elements contained within this block - can be
- * called for either the entire HTML body, or for a div representing an
- * instance of a multiple-instance template.
- */
-jQuery.fn.initializeJSElements = function( partOfMultiple ) {
- this.find(".sfShowIfSelected").each( function() {
- jQuery(this)
- .showIfSelected(true)
- .change( function() {
- jQuery(this).showIfSelected(false);
- });
- });
-
- this.find(".sfShowIfChecked").each( function() {
- jQuery(this)
- .showIfChecked(true)
- .click( function() {
- jQuery(this).showIfChecked(false);
- });
- });
-
- this.find(".sfShowIfCheckedCheckbox").each( function() {
- jQuery(this)
- .showIfCheckedCheckbox(true)
- .click( function() {
- jQuery(this).showIfCheckedCheckbox(false);
- });
- });
-
- // Enable the new remove button
- this.find(".removeButton").click( function() {
-
- // Unregister initialization and validation for deleted inputs
- jQuery(this).parentsUntil( '.multipleTemplateInstance' ).last().parent().find("input, select, textarea").each(
- function() {
- jQuery(this).SemanticForms_unregisterInputInit();
- jQuery(this).SemanticForms_unregisterInputValidation();
- }
- );
-
- // Remove the encompassing div for this instance.
- jQuery(this).closest(".multipleTemplateInstance")
- .fadeTo('fast', 0, function() {
- jQuery(this).slideUp('fast', function() {
- jQuery(this).remove();
- });
- });
- return false;
- });
-
- // ...and the new adder
- if ( partOfMultiple ) {
- this.find('.addAboveButton').click( function() {
- jQuery(this).addInstance( true );
- return false; // needed to disable <a> behavior
- });
- }
-
- this.find('.autocompleteInput').attachAutocomplete();
-
- var combobox = new sf.select2.combobox();
- this.find('.sfComboBox').not('#semantic_property_starter, .multipleTemplateStarter .sfComboBox, .select2-container').each( function() {
- combobox.apply($(this));
- });
-
- var tokens = new sf.select2.tokens();
- this.find('.sfTokens').not('.multipleTemplateStarter .sfTokens, .select2-container').each( function() {
- tokens.apply($(this));
- });
-
- this.find('.autoGrow').autoGrow();
- this.find('.sfFancyBox').fancybox({
- 'width' : '75%',
- 'height' : '75%',
- 'autoScale' : false,
- 'transitionIn' : 'none',
- 'transitionOut' : 'none',
- 'type' : 'iframe',
- 'overlayColor' : '#222',
- 'overlayOpacity' : '0.8'
- });
-
- // @TODO - this should ideally be called only for inputs that have
- // a dependent field - which might involve changing the storage of
- // "dependent fields" information from a global variable to a
- // per-input HTML attribute.
- this.find('input, select').each( function() {
- jQuery(this)
- .setAutocompleteForDependentField( partOfMultiple )
- .blur( function() {
- jQuery(this).setAutocompleteForDependentField( partOfMultiple );
- });
- });
- // The 'blur' event doesn't get triggered for radio buttons for
- // Chrome and Safari (the WebKit-based browsers) so use the 'change'
- // event in addition.
- // @TODO - blur() shuldn't be called at all for radio buttons.
- this.find('input:radio')
- .change( function() {
- jQuery(this).setAutocompleteForDependentField( partOfMultiple );
- });
-};
-
-var num_elements = 0;
-
-// Once the document has finished loading, set up everything!
-jQuery(document).ready(function() {
- jQuery('body').initializeJSElements();
-
- jQuery('.multipleTemplateInstance').initializeJSElements(true);
- jQuery('.multipleTemplateAdder').click( function() {
- jQuery(this).addInstance( false );
- });
- jQuery('.multipleTemplateList').sortable({
- axis: 'y',
- handle: '.rearrangerImage'
- });
-
-
- // If the form is submitted, validate everything!
- jQuery('#sfForm').submit( function() {return validateAll();} );
-});
diff --git a/SemanticForms/libs/ext.dynatree.js b/SemanticForms/libs/ext.dynatree.js
deleted file mode 100644
index 116b04d9..00000000
--- a/SemanticForms/libs/ext.dynatree.js
+++ /dev/null
@@ -1,52 +0,0 @@
-$(function () {
- // Attach the dynatree widget to an existing <div id="tree"> element
- // and pass the tree options as an argument to the dynatree() function:
- var nodeSelection = $("div[id*=treeinput]");
- nodeSelection.each (function (index) {
- var node = nodeSelection.eq(index);
- var selectMode = 2;
- var checkboxClass = {checkbox: "dynatree-checkbox"};
- if (node.find(":input:radio").length) {
- selectMode = 1;
- checkboxClass = {checkbox: "dynatree-radio"};
- }
-
- node.dynatree({
- checkbox: true,
- minExpandLevel: 1,
- classNames: checkboxClass,
- selectMode: selectMode,
- onClick: function (node, event) {
- var targetType = node.getEventTargetType(event);
- if ( targetType == "expander" ) {
- node.toggleExpand();
- } else if ( targetType == "checkbox" ||
- targetType == "title" ) {
- node.toggleSelect();
- }
-
- return false;
- },
- //Un/check real checkboxes recursively after selection
- onSelect: function (select, dtnode) {
- var inputkey = "chb-" + dtnode.data.key;
- $("[id='" + inputkey + "']").attr("checked", select);
- },
- //Prevent reappearing of checkbox when node is collapse
- onExpand: function (select, dtnode) {
- $("#chb-" + dtnode.data.key).attr("checked",
- dtnode.isSelected()).addClass("hidden");
- }
- });
- //Update real checkboxes according to selections
- $.map(node.dynatree("getTree").getSelectedNodes(),
- function (dtnode) {
- $("#chb-" + dtnode.data.key).attr("checked", true);
- dtnode.activate();
- });
- var activeNode = node.dynatree("getTree").getActiveNode();
- if (activeNode !== null) {
- activeNode.deactivate();
- }
- });
-});
diff --git a/SemanticForms/libs/ext.sf.js b/SemanticForms/libs/ext.sf.js
deleted file mode 100644
index 5a75217f..00000000
--- a/SemanticForms/libs/ext.sf.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-* ext.sf.js
-*
-* @file
-*
-*
-* @licence GNU GPL v2+
-* @author Jatin Mehta
-*
-*/
-
-var sf = ( function ( $, undefined ) {
- 'use strict';
- /**
- *
- * Declares methods and properties that are available through the sf namespace
- *
- * @class sf
- * @alternateClassName semanticforms
- * @singleton
- */
- return {
-
- };
-} )( jQuery );
-
-//Assinging namespace
-window.sf = window.semanticforms = sf; \ No newline at end of file
diff --git a/SemanticForms/libs/ext.sf.select2.base.js b/SemanticForms/libs/ext.sf.select2.base.js
deleted file mode 100644
index 0a9c5900..00000000
--- a/SemanticForms/libs/ext.sf.select2.base.js
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
-* ext.sf.select2.base.js
-*
-* Base class to handle autocomplete
-* for various input types using Select2 JS library
-*
-* @file
-*
-*
-* @licence GNU GPL v2+
-* @author Jatin Mehta
-*
-*/
-
-( function ( $, mw, sf ) {
- 'use strict';
- /**
- * Inheritance class for the sf.select2 constructor
- *
- *
- * @class
- */
- sf.select2 = sf.select2 || {};
-
- /**
- * Class constructor
- *
- *
- * @class
- * @constructor
- */
- sf.select2.base = function() {
-
- };
-
- sf.select2.base.prototype = {
- /*
- * Applies select2 to the HTML element
- *
- * @param {HTMLElement} element
- *
- */
- apply: function( element ) {
- this.id = element.attr( "id" );
- var opts = this.setOptions();
-
- element.select2(opts);
- element.on( "change", this.onChange );
- },
- /*
- * Used to remove the select2 applied to the HTML element,
- * the selected value will remain preserved.
- *
- * @param {HTMLElement} element
- *
- */
- destroy: function( element ) {
- element.select2( "destroy" );
- },
- /*
- * Returns HTML text to be used by select2 for
- * showing remote data retrieved
- *
- * @param {object} value
- * @param {object} container
- * @param {object} query
- *
- * @return {string} markup
- *
- */
- formatResult: function(value, container, query) {
- var term = query.term;
- var text = value.text;
- var image = value.image;
- var description = value.description;
- var markup = "";
-
- var text_highlight = sf.select2.base.prototype.textHighlight;
- if ( text !== undefined && image !== undefined && description !== undefined ) {
- markup += "<table class='sf-select2-result'> <tr>";
- markup += "<td class='sf-result-thumbnail'><img src='" + image + "'/></td>";
- markup += "<td class='sf-result-info'><div class='sf-result-title'>" + text_highlight(text, term) + "</div>";
- markup += "<div class='sf-result-description'>" + description + "</div>";
- markup += "</td></tr></table>";
- } else if ( text !== undefined && image !== undefined ) {
- markup += "<img class='sf-icon' src='"+ image +"'/>" + text_highlight(text, term);
- } else if ( text !== undefined && description !== undefined ) {
- markup += "<table class='sf-select2-result'> <tr>";
- markup += "<td class='sf-result-info'><div class='sf-result-title'>" + text_highlight(text, term) + "</div>";
- markup += "<div class='sf-result-description'>" + description + "</div>";
- markup += "</td></tr></table>";
- } else {
- markup += text_highlight(text, term);
- }
-
- return markup;
- },
- /*
- * Returns string/HTML text to be used by select2 to
- * show selection
- *
- * @param {object} value (The selected result object)
- *
- * @return {string}
- *
- */
- formatSelection: function(value) {
- return value.text;
- },
- /*
- * If a field is dependent on some other field in the form
- * then it returns its name.
- *
- * @return {string}
- *
- */
- dependentOn: function() {
- var input_id = "#" + this.id;
- var name_attr = this.nameAttr( $(input_id) );
- var name = $(input_id).attr( name_attr );
-
- var sfgDependentFields = mw.config.get( 'sfgDependentFields' );
- for ( var i = 0; i < sfgDependentFields.length; i++ ) {
- var dependentFieldPair = sfgDependentFields[i];
- if ( dependentFieldPair[1] == name ) {
- return dependentFieldPair[0];
- }
- }
- return null;
- },
- /*
- * Returns the array of names of fields in the form which are dependent
- * on the field passed as a param to this function,
- *
- * @param {HTMLElement} element
- *
- * @return {associative array} dependent_on_me
- *
- */
- dependentOnMe: function( element ) {
- var name_attr = this.nameAttr(element);
- var name = element.attr( name_attr );
- var dependent_on_me = [];
-
- var sfgDependentFields = mw.config.get( 'sfgDependentFields' );
- for ( var i = 0; i < sfgDependentFields.length; i++ ) {
- var dependentFieldPair = sfgDependentFields[i];
- if ( dependentFieldPair[0] == name ) {
- dependent_on_me.push(dependentFieldPair[1]);
- }
- }
-
- return dependent_on_me;
- },
- /*
- * Returns the name attribute of the field depending on
- * whether it is a part of multiple instance template or not
- *
- * @param {HTMLElement} element
- *
- * @return {string}
- *
- */
- nameAttr: function( element ) {
- return this.partOfMultiple( element ) ? "origname" : "name";
- },
- /*
- * Checks whether the field is part of multiple instance template or not
- *
- * @param {HTMLElement} element
- *
- * @return {boolean}
- *
- */
- partOfMultiple: function( element ) {
- return element.attr( "origname" ) !== undefined ? true : false;
- },
- /*
- * Gives dependent field options which include
- * property, base property and base value
- *
- * @param {string} dep_on
- *
- * @return {object} dep_field_opts
- *
- */
- getDependentFieldOpts: function( dep_on ) {
- var input_id = "#" + this.id;
- var dep_field_opts = {};
- var base_element;
- if ( this.partOfMultiple($(input_id)) ) {
- base_element = $(input_id).closest( ".multipleTemplateInstance" )
- .find( '[origname ="' + dep_on + '" ]' );
- } else {
- base_element = $('[name ="' + dep_on + '" ]');
- }
- dep_field_opts.base_value = base_element.val();
- dep_field_opts.base_prop = base_element.attr( "autocompletesettings" );
- dep_field_opts.prop = $(input_id).attr( "autocompletesettings" ).split( "," )[0];
-
- return dep_field_opts;
- },
- /*
- * Gives autocomplete options for a field
- *
- *
- * @return {object} autocomplete_opts
- *
- */
- getAutocompleteOpts: function() {
- var input_id = "#" + this.id;
- var autocomplete_opts = {};
- autocomplete_opts.autocompletedatatype = $(input_id).attr( "autocompletedatatype" );
- autocomplete_opts.autocompletesettings = $(input_id).attr( "autocompletesettings" );
-
- return autocomplete_opts;
- },
- /*
- * Refreshes the field if there is a change
- * in the autocomplete vlaues
- *
- * @param {HTMLElement} element
- *
- */
- refresh: function( element ) {
- this.destroy($(element));
- this.apply($(element));
- },
- /*
- * Removes diacritics from the string and replaces
- * them with english characters.
- * This code is basically copied from:
- * http://jsfiddle.net/potherca/Gtmr2/
- *
- * @param {string} text
- *
- * @return {string}
- *
- */
- removeDiacritics: function( text ) {
- var diacriticsMap = { 'Á': 'A', 'Ă': 'A', 'Ắ': 'A', 'Ặ': 'A', 'Ằ': 'A', 'Ẳ': 'A', 'Ẵ': 'A', 'Ǎ': 'A', 'Â': 'A', 'Ấ': 'A', 'Ậ': 'A', 'Ầ': 'A', 'Ẩ': 'A', 'Ẫ': 'A', 'Ä': 'A', 'Ǟ': 'A', 'Ȧ': 'A', 'Ǡ': 'A', 'Ạ': 'A', 'Ȁ': 'A', 'À': 'A', 'Ả': 'A', 'Ȃ': 'A', 'Ā': 'A', 'Ą': 'A', 'Å': 'A', 'Ǻ': 'A', 'Ḁ': 'A', 'Ⱥ': 'A', 'Ã': 'A', 'Ꜳ': 'AA', 'Æ': 'AE', 'Ǽ': 'AE', 'Ǣ': 'AE', 'Ꜵ': 'AO', 'Ꜷ': 'AU', 'Ꜹ': 'AV', 'Ꜻ': 'AV', 'Ꜽ': 'AY', 'Ḃ': 'B', 'Ḅ': 'B', 'Ɓ': 'B', 'Ḇ': 'B', 'Ƀ': 'B', 'Ƃ': 'B', 'Ć': 'C', 'Č': 'C', 'Ç': 'C', 'Ḉ': 'C', 'Ĉ': 'C', 'Ċ': 'C', 'Ƈ': 'C', 'Ȼ': 'C', 'Ď': 'D', 'Ḑ': 'D', 'Ḓ': 'D', 'Ḋ': 'D', 'Ḍ': 'D', 'Ɗ': 'D', 'Ḏ': 'D', 'Dz': 'D', 'Dž': 'D', 'Đ': 'D', 'Ƌ': 'D', 'DZ': 'DZ', 'DŽ': 'DZ', 'É': 'E', 'Ĕ': 'E', 'Ě': 'E', 'Ȩ': 'E', 'Ḝ': 'E', 'Ê': 'E', 'Ế': 'E', 'Ệ': 'E', 'Ề': 'E', 'Ể': 'E', 'Ễ': 'E', 'Ḙ': 'E', 'Ë': 'E', 'Ė': 'E', 'Ẹ': 'E', 'Ȅ': 'E', 'È': 'E', 'Ẻ': 'E', 'Ȇ': 'E', 'Ē': 'E', 'Ḗ': 'E', 'Ḕ': 'E', 'Ę': 'E', 'Ɇ': 'E', 'Ẽ': 'E', 'Ḛ': 'E', 'Ꝫ': 'ET', 'Ḟ': 'F', 'Ƒ': 'F', 'Ǵ': 'G', 'Ğ': 'G', 'Ǧ': 'G', 'Ģ': 'G', 'Ĝ': 'G', 'Ġ': 'G', 'Ɠ': 'G', 'Ḡ': 'G', 'Ǥ': 'G', 'Ḫ': 'H', 'Ȟ': 'H', 'Ḩ': 'H', 'Ĥ': 'H', 'Ⱨ': 'H', 'Ḧ': 'H', 'Ḣ': 'H', 'Ḥ': 'H', 'Ħ': 'H', 'Í': 'I', 'Ĭ': 'I', 'Ǐ': 'I', 'Î': 'I', 'Ï': 'I', 'Ḯ': 'I', 'İ': 'I', 'Ị': 'I', 'Ȉ': 'I', 'Ì': 'I', 'Ỉ': 'I', 'Ȋ': 'I', 'Ī': 'I', 'Į': 'I', 'Ɨ': 'I', 'Ĩ': 'I', 'Ḭ': 'I', 'Ꝺ': 'D', 'Ꝼ': 'F', 'Ᵹ': 'G', 'Ꞃ': 'R', 'Ꞅ': 'S', 'Ꞇ': 'T', 'Ꝭ': 'IS', 'Ĵ': 'J', 'Ɉ': 'J', 'Ḱ': 'K', 'Ǩ': 'K', 'Ķ': 'K', 'Ⱪ': 'K', 'Ꝃ': 'K', 'Ḳ': 'K', 'Ƙ': 'K', 'Ḵ': 'K', 'Ꝁ': 'K', 'Ꝅ': 'K', 'Ĺ': 'L', 'Ƚ': 'L', 'Ľ': 'L', 'Ļ': 'L', 'Ḽ': 'L', 'Ḷ': 'L', 'Ḹ': 'L', 'Ⱡ': 'L', 'Ꝉ': 'L', 'Ḻ': 'L', 'Ŀ': 'L', 'Ɫ': 'L', 'Lj': 'L', 'Ł': 'L', 'LJ': 'LJ', 'Ḿ': 'M', 'Ṁ': 'M', 'Ṃ': 'M', 'Ɱ': 'M', 'Ń': 'N', 'Ň': 'N', 'Ņ': 'N', 'Ṋ': 'N', 'Ṅ': 'N', 'Ṇ': 'N', 'Ǹ': 'N', 'Ɲ': 'N', 'Ṉ': 'N', 'Ƞ': 'N', 'Nj': 'N', 'Ñ': 'N', 'NJ': 'NJ', 'Ó': 'O', 'Ŏ': 'O', 'Ǒ': 'O', 'Ô': 'O', 'Ố': 'O', 'Ộ': 'O', 'Ồ': 'O', 'Ổ': 'O', 'Ỗ': 'O', 'Ö': 'O', 'Ȫ': 'O', 'Ȯ': 'O', 'Ȱ': 'O', 'Ọ': 'O', 'Ő': 'O', 'Ȍ': 'O', 'Ò': 'O', 'Ỏ': 'O', 'Ơ': 'O', 'Ớ': 'O', 'Ợ': 'O', 'Ờ': 'O', 'Ở': 'O', 'Ỡ': 'O', 'Ȏ': 'O', 'Ꝋ': 'O', 'Ꝍ': 'O', 'Ō': 'O', 'Ṓ': 'O', 'Ṑ': 'O', 'Ɵ': 'O', 'Ǫ': 'O', 'Ǭ': 'O', 'Ø': 'O', 'Ǿ': 'O', 'Õ': 'O', 'Ṍ': 'O', 'Ṏ': 'O', 'Ȭ': 'O', 'Ƣ': 'OI', 'Ꝏ': 'OO', 'Ɛ': 'E', 'Ɔ': 'O', 'Ȣ': 'OU', 'Ṕ': 'P', 'Ṗ': 'P', 'Ꝓ': 'P', 'Ƥ': 'P', 'Ꝕ': 'P', 'Ᵽ': 'P', 'Ꝑ': 'P', 'Ꝙ': 'Q', 'Ꝗ': 'Q', 'Ŕ': 'R', 'Ř': 'R', 'Ŗ': 'R', 'Ṙ': 'R', 'Ṛ': 'R', 'Ṝ': 'R', 'Ȑ': 'R', 'Ȓ': 'R', 'Ṟ': 'R', 'Ɍ': 'R', 'Ɽ': 'R', 'Ꜿ': 'C', 'Ǝ': 'E', 'Ś': 'S', 'Ṥ': 'S', 'Š': 'S', 'Ṧ': 'S', 'Ş': 'S', 'Ŝ': 'S', 'Ș': 'S', 'Ṡ': 'S', 'Ṣ': 'S', 'Ṩ': 'S', 'ẞ': 'SS', 'Ť': 'T', 'Ţ': 'T', 'Ṱ': 'T', 'Ț': 'T', 'Ⱦ': 'T', 'Ṫ': 'T', 'Ṭ': 'T', 'Ƭ': 'T', 'Ṯ': 'T', 'Ʈ': 'T', 'Ŧ': 'T', 'Ɐ': 'A', 'Ꞁ': 'L', 'Ɯ': 'M', 'Ʌ': 'V', 'Ꜩ': 'TZ', 'Ú': 'U', 'Ŭ': 'U', 'Ǔ': 'U', 'Û': 'U', 'Ṷ': 'U', 'Ü': 'U', 'Ǘ': 'U', 'Ǚ': 'U', 'Ǜ': 'U', 'Ǖ': 'U', 'Ṳ': 'U', 'Ụ': 'U', 'Ű': 'U', 'Ȕ': 'U', 'Ù': 'U', 'Ủ': 'U', 'Ư': 'U', 'Ứ': 'U', 'Ự': 'U', 'Ừ': 'U', 'Ử': 'U', 'Ữ': 'U', 'Ȗ': 'U', 'Ū': 'U', 'Ṻ': 'U', 'Ų': 'U', 'Ů': 'U', 'Ũ': 'U', 'Ṹ': 'U', 'Ṵ': 'U', 'Ꝟ': 'V', 'Ṿ': 'V', 'Ʋ': 'V', 'Ṽ': 'V', 'Ꝡ': 'VY', 'Ẃ': 'W', 'Ŵ': 'W', 'Ẅ': 'W', 'Ẇ': 'W', 'Ẉ': 'W', 'Ẁ': 'W', 'Ⱳ': 'W', 'Ẍ': 'X', 'Ẋ': 'X', 'Ý': 'Y', 'Ŷ': 'Y', 'Ÿ': 'Y', 'Ẏ': 'Y', 'Ỵ': 'Y', 'Ỳ': 'Y', 'Ƴ': 'Y', 'Ỷ': 'Y', 'Ỿ': 'Y', 'Ȳ': 'Y', 'Ɏ': 'Y', 'Ỹ': 'Y', 'Ź': 'Z', 'Ž': 'Z', 'Ẑ': 'Z', 'Ⱬ': 'Z', 'Ż': 'Z', 'Ẓ': 'Z', 'Ȥ': 'Z', 'Ẕ': 'Z', 'Ƶ': 'Z', 'IJ': 'IJ', 'Œ': 'OE', 'ᴀ': 'A', 'ᴁ': 'AE', 'ʙ': 'B', 'ᴃ': 'B', 'ᴄ': 'C', 'ᴅ': 'D', 'ᴇ': 'E', 'ꜰ': 'F', 'ɢ': 'G', 'ʛ': 'G', 'ʜ': 'H', 'ɪ': 'I', 'ʁ': 'R', 'ᴊ': 'J', 'ᴋ': 'K', 'ʟ': 'L', 'ᴌ': 'L', 'ᴍ': 'M', 'ɴ': 'N', 'ᴏ': 'O', 'ɶ': 'OE', 'ᴐ': 'O', 'ᴕ': 'OU', 'ᴘ': 'P', 'ʀ': 'R', 'ᴎ': 'N', 'ᴙ': 'R', 'ꜱ': 'S', 'ᴛ': 'T', 'ⱻ': 'E', 'ᴚ': 'R', 'ᴜ': 'U', 'ᴠ': 'V', 'ᴡ': 'W', 'ʏ': 'Y', 'ᴢ': 'Z', 'á': 'a', 'ă': 'a', 'ắ': 'a', 'ặ': 'a', 'ằ': 'a', 'ẳ': 'a', 'ẵ': 'a', 'ǎ': 'a', 'â': 'a', 'ấ': 'a', 'ậ': 'a', 'ầ': 'a', 'ẩ': 'a', 'ẫ': 'a', 'ä': 'a', 'ǟ': 'a', 'ȧ': 'a', 'ǡ': 'a', 'ạ': 'a', 'ȁ': 'a', 'à': 'a', 'ả': 'a', 'ȃ': 'a', 'ā': 'a', 'ą': 'a', 'ᶏ': 'a', 'ẚ': 'a', 'å': 'a', 'ǻ': 'a', 'ḁ': 'a', 'ⱥ': 'a', 'ã': 'a', 'ꜳ': 'aa', 'æ': 'ae', 'ǽ': 'ae', 'ǣ': 'ae', 'ꜵ': 'ao', 'ꜷ': 'au', 'ꜹ': 'av', 'ꜻ': 'av', 'ꜽ': 'ay', 'ḃ': 'b', 'ḅ': 'b', 'ɓ': 'b', 'ḇ': 'b', 'ᵬ': 'b', 'ᶀ': 'b', 'ƀ': 'b', 'ƃ': 'b', 'ɵ': 'o', 'ć': 'c', 'č': 'c', 'ç': 'c', 'ḉ': 'c', 'ĉ': 'c', 'ɕ': 'c', 'ċ': 'c', 'ƈ': 'c', 'ȼ': 'c', 'ď': 'd', 'ḑ': 'd', 'ḓ': 'd', 'ȡ': 'd', 'ḋ': 'd', 'ḍ': 'd', 'ɗ': 'd', 'ᶑ': 'd', 'ḏ': 'd', 'ᵭ': 'd', 'ᶁ': 'd', 'đ': 'd', 'ɖ': 'd', 'ƌ': 'd', 'ı': 'i', 'ȷ': 'j', 'ɟ': 'j', 'ʄ': 'j', 'dz': 'dz', 'dž': 'dz', 'é': 'e', 'ĕ': 'e', 'ě': 'e', 'ȩ': 'e', 'ḝ': 'e', 'ê': 'e', 'ế': 'e', 'ệ': 'e', 'ề': 'e', 'ể': 'e', 'ễ': 'e', 'ḙ': 'e', 'ë': 'e', 'ė': 'e', 'ẹ': 'e', 'ȅ': 'e', 'è': 'e', 'ẻ': 'e', 'ȇ': 'e', 'ē': 'e', 'ḗ': 'e', 'ḕ': 'e', 'ⱸ': 'e', 'ę': 'e', 'ᶒ': 'e', 'ɇ': 'e', 'ẽ': 'e', 'ḛ': 'e', 'ꝫ': 'et', 'ḟ': 'f', 'ƒ': 'f', 'ᵮ': 'f', 'ᶂ': 'f', 'ǵ': 'g', 'ğ': 'g', 'ǧ': 'g', 'ģ': 'g', 'ĝ': 'g', 'ġ': 'g', 'ɠ': 'g', 'ḡ': 'g', 'ᶃ': 'g', 'ǥ': 'g', 'ḫ': 'h', 'ȟ': 'h', 'ḩ': 'h', 'ĥ': 'h', 'ⱨ': 'h', 'ḧ': 'h', 'ḣ': 'h', 'ḥ': 'h', 'ɦ': 'h', 'ẖ': 'h', 'ħ': 'h', 'ƕ': 'hv', 'í': 'i', 'ĭ': 'i', 'ǐ': 'i', 'î': 'i', 'ï': 'i', 'ḯ': 'i', 'ị': 'i', 'ȉ': 'i', 'ì': 'i', 'ỉ': 'i', 'ȋ': 'i', 'ī': 'i', 'į': 'i', 'ᶖ': 'i', 'ɨ': 'i', 'ĩ': 'i', 'ḭ': 'i', 'ꝺ': 'd', 'ꝼ': 'f', 'ᵹ': 'g', 'ꞃ': 'r', 'ꞅ': 's', 'ꞇ': 't', 'ꝭ': 'is', 'ǰ': 'j', 'ĵ': 'j', 'ʝ': 'j', 'ɉ': 'j', 'ḱ': 'k', 'ǩ': 'k', 'ķ': 'k', 'ⱪ': 'k', 'ꝃ': 'k', 'ḳ': 'k', 'ƙ': 'k', 'ḵ': 'k', 'ᶄ': 'k', 'ꝁ': 'k', 'ꝅ': 'k', 'ĺ': 'l', 'ƚ': 'l', 'ɬ': 'l', 'ľ': 'l', 'ļ': 'l', 'ḽ': 'l', 'ȴ': 'l', 'ḷ': 'l', 'ḹ': 'l', 'ⱡ': 'l', 'ꝉ': 'l', 'ḻ': 'l', 'ŀ': 'l', 'ɫ': 'l', 'ᶅ': 'l', 'ɭ': 'l', 'ł': 'l', 'lj': 'lj', 'ſ': 's', 'ẜ': 's', 'ẛ': 's', 'ẝ': 's', 'ḿ': 'm', 'ṁ': 'm', 'ṃ': 'm', 'ɱ': 'm', 'ᵯ': 'm', 'ᶆ': 'm', 'ń': 'n', 'ň': 'n', 'ņ': 'n', 'ṋ': 'n', 'ȵ': 'n', 'ṅ': 'n', 'ṇ': 'n', 'ǹ': 'n', 'ɲ': 'n', 'ṉ': 'n', 'ƞ': 'n', 'ᵰ': 'n', 'ᶇ': 'n', 'ɳ': 'n', 'ñ': 'n', 'nj': 'nj', 'ó': 'o', 'ŏ': 'o', 'ǒ': 'o', 'ô': 'o', 'ố': 'o', 'ộ': 'o', 'ồ': 'o', 'ổ': 'o', 'ỗ': 'o', 'ö': 'o', 'ȫ': 'o', 'ȯ': 'o', 'ȱ': 'o', 'ọ': 'o', 'ő': 'o', 'ȍ': 'o', 'ò': 'o', 'ỏ': 'o', 'ơ': 'o', 'ớ': 'o', 'ợ': 'o', 'ờ': 'o', 'ở': 'o', 'ỡ': 'o', 'ȏ': 'o', 'ꝋ': 'o', 'ꝍ': 'o', 'ⱺ': 'o', 'ō': 'o', 'ṓ': 'o', 'ṑ': 'o', 'ǫ': 'o', 'ǭ': 'o', 'ø': 'o', 'ǿ': 'o', 'õ': 'o', 'ṍ': 'o', 'ṏ': 'o', 'ȭ': 'o', 'ƣ': 'oi', 'ꝏ': 'oo', 'ɛ': 'e', 'ᶓ': 'e', 'ɔ': 'o', 'ᶗ': 'o', 'ȣ': 'ou', 'ṕ': 'p', 'ṗ': 'p', 'ꝓ': 'p', 'ƥ': 'p', 'ᵱ': 'p', 'ᶈ': 'p', 'ꝕ': 'p', 'ᵽ': 'p', 'ꝑ': 'p', 'ꝙ': 'q', 'ʠ': 'q', 'ɋ': 'q', 'ꝗ': 'q', 'ŕ': 'r', 'ř': 'r', 'ŗ': 'r', 'ṙ': 'r', 'ṛ': 'r', 'ṝ': 'r', 'ȑ': 'r', 'ɾ': 'r', 'ᵳ': 'r', 'ȓ': 'r', 'ṟ': 'r', 'ɼ': 'r', 'ᵲ': 'r', 'ᶉ': 'r', 'ɍ': 'r', 'ɽ': 'r', 'ↄ': 'c', 'ꜿ': 'c', 'ɘ': 'e', 'ɿ': 'r', 'ś': 's', 'ṥ': 's', 'š': 's', 'ṧ': 's', 'ş': 's', 'ŝ': 's', 'ș': 's', 'ṡ': 's', 'ṣ': 's', 'ṩ': 's', 'ʂ': 's', 'ᵴ': 's', 'ᶊ': 's', 'ȿ': 's', 'ß': 'ss', 'ɡ': 'g', 'ᴑ': 'o', 'ᴓ': 'o', 'ᴝ': 'u', 'ť': 't', 'ţ': 't', 'ṱ': 't', 'ț': 't', 'ȶ': 't', 'ẗ': 't', 'ⱦ': 't', 'ṫ': 't', 'ṭ': 't', 'ƭ': 't', 'ṯ': 't', 'ᵵ': 't', 'ƫ': 't', 'ʈ': 't', 'ŧ': 't', 'ᵺ': 'th', 'ɐ': 'a', 'ᴂ': 'ae', 'ǝ': 'e', 'ᵷ': 'g', 'ɥ': 'h', 'ʮ': 'h', 'ʯ': 'h', 'ᴉ': 'i', 'ʞ': 'k', 'ꞁ': 'l', 'ɯ': 'm', 'ɰ': 'm', 'ᴔ': 'oe', 'ɹ': 'r', 'ɻ': 'r', 'ɺ': 'r', 'ⱹ': 'r', 'ʇ': 't', 'ʌ': 'v', 'ʍ': 'w', 'ʎ': 'y', 'ꜩ': 'tz', 'ú': 'u', 'ŭ': 'u', 'ǔ': 'u', 'û': 'u', 'ṷ': 'u', 'ü': 'u', 'ǘ': 'u', 'ǚ': 'u', 'ǜ': 'u', 'ǖ': 'u', 'ṳ': 'u', 'ụ': 'u', 'ű': 'u', 'ȕ': 'u', 'ù': 'u', 'ủ': 'u', 'ư': 'u', 'ứ': 'u', 'ự': 'u', 'ừ': 'u', 'ử': 'u', 'ữ': 'u', 'ȗ': 'u', 'ū': 'u', 'ṻ': 'u', 'ų': 'u', 'ᶙ': 'u', 'ů': 'u', 'ũ': 'u', 'ṹ': 'u', 'ṵ': 'u', 'ᵫ': 'ue', 'ꝸ': 'um', 'ⱴ': 'v', 'ꝟ': 'v', 'ṿ': 'v', 'ʋ': 'v', 'ᶌ': 'v', 'ⱱ': 'v', 'ṽ': 'v', 'ꝡ': 'vy', 'ẃ': 'w', 'ŵ': 'w', 'ẅ': 'w', 'ẇ': 'w', 'ẉ': 'w', 'ẁ': 'w', 'ⱳ': 'w', 'ẘ': 'w', 'ẍ': 'x', 'ẋ': 'x', 'ᶍ': 'x', 'ý': 'y', 'ŷ': 'y', 'ÿ': 'y', 'ẏ': 'y', 'ỵ': 'y', 'ỳ': 'y', 'ƴ': 'y', 'ỷ': 'y', 'ỿ': 'y', 'ȳ': 'y', 'ẙ': 'y', 'ɏ': 'y', 'ỹ': 'y', 'ź': 'z', 'ž': 'z', 'ẑ': 'z', 'ʑ': 'z', 'ⱬ': 'z', 'ż': 'z', 'ẓ': 'z', 'ȥ': 'z', 'ẕ': 'z', 'ᵶ': 'z', 'ᶎ': 'z', 'ʐ': 'z', 'ƶ': 'z', 'ɀ': 'z', 'ff': 'ff', 'ffi': 'ffi', 'ffl': 'ffl', 'fi': 'fi', 'fl': 'fl', 'ij': 'ij', 'œ': 'oe', 'st': 'st', 'ₐ': 'a', 'ₑ': 'e', 'ᵢ': 'i', 'ⱼ': 'j', 'ₒ': 'o', 'ᵣ': 'r', 'ᵤ': 'u', 'ᵥ': 'v', 'ₓ': 'x' };
-
- return text.replace(/[\u007F-\uFFFF]/g, function(key) {
- return diacriticsMap[key] || key;
- });
- },
- textHighlight: function( text, term ) {
- var markup = "";
- var remove_diacritics = sf.select2.base.prototype.removeDiacritics;
- var no_diac_text = remove_diacritics(text);
- var start = no_diac_text.toUpperCase().indexOf(term.toUpperCase());
- if (start !== 0 && !mw.config.get( 'sfgAutocompleteOnAllChars' )) {
- start = no_diac_text.toUpperCase().indexOf(" " + term.toUpperCase());
- if ( start != -1 ) {
- start = start + 1;
- }
- }
- if ( start != -1 ) {
- markup += text.substr(0, start) +
- '<span class="select2-match">' +
- text.substr(start,term.length) +
- '</span>' +
- text.substr(start + term.length, text.length);
- } else {
- markup += text;
- }
-
- return markup;
- },
- };
-} )( jQuery, mediaWiki, semanticforms ); \ No newline at end of file
diff --git a/SemanticForms/libs/ext.sf.select2.combobox.js b/SemanticForms/libs/ext.sf.select2.combobox.js
deleted file mode 100644
index cccfab9d..00000000
--- a/SemanticForms/libs/ext.sf.select2.combobox.js
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * ext.sf.select2.comboboxjs
- *
- * Javascript utility class to handle autocomplete
- * for combobox input type using Select2 JS library
- *
- * @file
- *
- * @licence GNU GPL v2+
- * @author Jatin Mehta
- */
-
-( function( $, mw, sf ) {
- 'use strict';
-
- /**
- * Inheritance class for the sf.select2 constructor
- *
- *
- * @class
- */
- sf.select2 = sf.select2 || {};
-
- /**
- * Class constructor
- *
- *
- * @class
- * @constructor
- */
- sf.select2.combobox = function() {
-
- };
-
- var combobox_proto = new sf.select2.base();
-
- /*
- * Returns options to be set by select2
- *
- * @return {object} opts
- *
- */
- combobox_proto.setOptions = function() {
- var input_id = this.id;
- var opts = {};
- input_id = "#" + input_id;
- var input_tagname = $(input_id).prop( "tagName" );
- var autocomplete_opts = this.getAutocompleteOpts();
-
- if ( autocomplete_opts.autocompletedatatype !== undefined ) {
- opts.ajax = this.getAjaxOpts();
- opts.minimumInputLength = 1;
- opts.formatInputTooShort = mw.msg( "sf-select2-input-too-short", opts.minimumInputLength );
- opts.formatSelection = this.formatSelection;
- opts.escapeMarkup = function (m) { return m; };
- } else if ( input_tagname == "INPUT" ) {
- opts.data = this.getData( autocomplete_opts.autocompletesettings );
- }
- var sfgAutocompleteOnAllChars = mw.config.get( 'sfgAutocompleteOnAllChars' );
- if ( !sfgAutocompleteOnAllChars ) {
- opts.matcher = function( term, text ) {
- var no_diac_text = sf.select2.base.prototype.removeDiacritics( text );
- var position = no_diac_text.toUpperCase().indexOf(term.toUpperCase());
- var position_with_space = no_diac_text.toUpperCase().indexOf(" " + term.toUpperCase());
- if ( (position != -1 && position === 0 ) || position_with_space != -1 ) {
- return true;
- } else {
- return false;
- }
- };
- }
- opts.formatResult = this.formatResult;
- opts.formatSearching = mw.msg( "sf-select2-searching" );
- opts.formatNoMatches = mw.msg( "sf-select2-no-matches" );
- opts.placeholder = $(input_id).attr( "placeholder" );
- if ( $(input_id).attr( "existingvaluesonly" ) !== "true" && input_tagname == "INPUT" ) {
- opts.createSearchChoice = function( term, data ) { if ( $(data).filter(function() { return this.text.localeCompare( term )===0; }).length===0 ) {return { id:term, text:term };} };
- }
- if ( $(input_id).val() !== "" && input_tagname == "INPUT" ) {
- opts.initSelection = function ( element, callback ) { var data = {id: element.val(), text: element.val()}; callback(data); };
- }
- opts.allowClear = true;
- var size = $(input_id).attr("size");
- if ( size === undefined ) {
- size = 35; //default value
- }
- opts.containerCss = { 'min-width': size * 6 };
- opts.containerCssClass = 'sf-select2-container';
- opts.dropdownCssClass = 'sf-select2-dropdown';
-
- return opts;
- };
- /*
- * Returns data to be used by select2 for combobox autocompletion
- *
- * @param {string} autocompletesettings
- * @return {associative array} values
- *
- */
- combobox_proto.getData = function( autocompletesettings ) {
- var input_id = "#" + this.id;
- var values = [{id: 0, text: ""}];
- var dep_on = this.dependentOn();
- var i, data;
- if ( dep_on === null ) {
- if ( autocompletesettings == 'external data' ) {
- var name = $(input_id).attr(this.nameAttr($(input_id)));
- var sfgEDSettings = mw.config.get( 'sfgEDSettings' );
- var edgValues = mw.config.get( 'edgValues' );
- data = {};
- if ( sfgEDSettings[name].title !== undefined && sfgEDSettings[name].title !== "" ) {
- data.title = edgValues[sfgEDSettings[name].title];
- i = 0;
- if ( data.title !== undefined && data.title !== null ) {
- data.title.forEach(function() {
- values.push({
- id: i + 1, text: data.title[i]
- });
- i++;
- });
- }
- if ( sfgEDSettings[name].image !== undefined && sfgEDSettings[name].image !== "" ) {
- data.image = edgValues[sfgEDSettings[name].image];
- i = 0;
- if ( data.image !== undefined && data.image !== null ) {
- data.image.forEach(function() {
- values[i+1].image = data.image[i];
- i++;
- });
- }
- }
- if ( sfgEDSettings[name].description !== undefined && sfgEDSettings[name].description !== "" ) {
- data.description = edgValues[sfgEDSettings[name].description];
- i = 0;
- if ( data.description !== undefined && data.description !== null ) {
- data.description.forEach(function() {
- values[i+1].description = data.description[i];
- i++;
- });
- }
- }
- }
-
- } else {
- var sfgAutocompleteValues = mw.config.get( 'sfgAutocompleteValues' );
- data = sfgAutocompleteValues[autocompletesettings];
- i = 0;
- //Convert data into the format accepted by Select2
- if (data !== undefined && data !== null ) {
- data.forEach(function()
- {
- values.push({
- id: i + 1, text: data[i]
- });
- i++;
- });
- }
- }
- } else { //Dependent field autocompletion
- var dep_field_opts = this.getDependentFieldOpts( dep_on );
- var my_server = mw.config.get( 'wgScriptPath' ) + "/api.php";
- my_server += "?action=sfautocomplete&format=json&property=" + dep_field_opts.prop + "&baseprop=" + dep_field_opts.base_prop + "&basevalue=" + dep_field_opts.base_value;
- $.ajax({
- url: my_server,
- dataType: 'json',
- async: false,
- success: function(data) {
- var id = 1;
- //Convert data into the format accepted by Select2
- data.sfautocomplete.forEach( function(item) {
- values.push({
- id: id++, text: item.title
- });
- });
- return values;
- }
- });
- }
-
- return values;
- };
- /*
- * Returns ajax options to be used by select2 for
- * remote autocompletion of combobox
- *
- * @return {object} ajaxOpts
- *
- */
- combobox_proto.getAjaxOpts = function() {
- var autocomplete_opts = this.getAutocompleteOpts();
- var my_server = mw.util.wikiScript( 'api' );
- my_server += "?action=sfautocomplete&format=json&" + autocomplete_opts.autocompletedatatype + "=" + autocomplete_opts.autocompletesettings;
-
- var ajaxOpts = {
- url: my_server,
- dataType: 'json',
- data: function (term) {
- return {
- substr: term, // search term
- };
- },
- results: function (data, page, query) { // parse the results into the format expected by Select2.
- var id = 0;
- if (data.sfautocomplete !== undefined) {
- data.sfautocomplete.forEach( function(item) {
- item.id = id++;
- item.text = item.title;
- });
- return {results: data.sfautocomplete};
- } else {
- return {results: []};
- }
- }
- };
-
- return ajaxOpts;
- };
- /*
- * Used to set the value of the HTMLInputElement
- * when there is a change in the select2 value
- *
- */
- combobox_proto.onChange = function() {
- var self = this;
- var data = $(this).select2( "data" );
- if (data !== null) {
- $(this).val( data.text );
- } else {
- $(this).val( '' );
- }
-
- // Set the corresponding values for any other field
- // in the form which is dependent on this element
- var cmbox = new sf.select2.combobox();
- var dep_on_me = $.unique(cmbox.dependentOnMe( $(this) ));
- dep_on_me.forEach( function( dependent_field_name ) {
- var dependent_field;
- if ( cmbox.partOfMultiple( $(self) ) ) {
- dependent_field = $(self).closest( ".multipleTemplateInstance" )
- .find( '[origname ="' + dependent_field_name + '" ]' );
- } else {
- dependent_field = $('[name ="' + dependent_field_name + '" ]');
- }
- cmbox.dependentFieldAutocompleteHandler( dependent_field, self );
- });
- };
- /*
- * Handles dependent field autocompletion
- *
- * @param {HTMLElement} dependent_field
- * @param {HTMLElement} dependent_on
- *
- */
- combobox_proto.dependentFieldAutocompleteHandler = function( dependent_field, dependent_on ) {
- var class_name = $(dependent_field).attr( 'class' );
- var cmbox = new sf.select2.combobox();
- var tokens = new sf.select2.tokens();
-
- if ( class_name.indexOf( 'sfComboBox' ) != -1 ) {
- cmbox.refresh(dependent_field);
- } else if ( class_name.indexOf( 'sfTokens' ) != -1 ) {
- tokens.refresh(dependent_field);
- } else if ( class_name.indexOf( 'createboxInput' ) != -1 ) {
- var name_attr = cmbox.nameAttr($(dependent_on));
- var field_name = $(dependent_field).attr(name_attr),
- base_field_name = $(dependent_on).attr(name_attr),
- base_value = $(dependent_on).val();
- $(dependent_field).setDependentAutocompletion(field_name, base_field_name, base_value);
- }
-
- };
-
- sf.select2.combobox.prototype = combobox_proto;
-
-} )( jQuery, mediaWiki, semanticforms ); \ No newline at end of file
diff --git a/SemanticForms/libs/ext.sf.select2.tokens.js b/SemanticForms/libs/ext.sf.select2.tokens.js
deleted file mode 100644
index 3be02233..00000000
--- a/SemanticForms/libs/ext.sf.select2.tokens.js
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * ext.sf.select2.tokens.js
- *
- * Javascript utility class to handle autocomplete
- * for tokens input type using Select2 JS library
- *
- * @file
- *
- * @licence GNU GPL v2+
- * @author Jatin Mehta
- */
-
-( function( $, mw, sf ) {
- 'use strict';
-
- /**
- * Inheritance class for the sf.select2 constructor
- *
- *
- * @class
- */
- sf.select2 = sf.select2 || {};
-
- /**
- * Class constructor
- *
- *
- * @class
- * @constructor
- */
- sf.select2.tokens = function() {
-
- };
-
- var tokens_proto = new sf.select2.base();
- /*
- * Applies select2 to the HTML element
- *
- * @param {HTMLElement} element
- *
- */
- tokens_proto.apply = function( element ) {
- this.id = element.attr( "id" );
- var opts = this.setOptions();
- var cur_val = element.val();
-
- element.select2(opts);
- this.sortable(element);
- element.on( "change", this.onChange );
- element.val(cur_val);
- };
- /*
- * Returns options to be set by select2
- *
- * @return {object} opts
- *
- */
- tokens_proto.setOptions = function() {
- var self = this;
- var input_id = this.id;
- var opts = {};
- input_id = "#" + input_id;
- var input_tagname = $(input_id).prop( "tagName" );
- var autocomplete_opts = this.getAutocompleteOpts();
-
- if ( autocomplete_opts.autocompletedatatype !== undefined ) {
- opts.ajax = this.getAjaxOpts();
- opts.minimumInputLength = 1;
- opts.formatInputTooShort = "";
- opts.formatSelection = this.formatSelection;
- opts.escapeMarkup = function (m) { return m; };
- } else if ( input_tagname == "INPUT" ) {
- opts.data = this.getData( autocomplete_opts.autocompletesettings );
- }
- var sfgAutocompleteOnAllChars = mw.config.get( 'sfgAutocompleteOnAllChars' );
- if ( !sfgAutocompleteOnAllChars ) {
- opts.matcher = function( term, text ) {
- var no_diac_text = sf.select2.base.prototype.removeDiacritics( text );
- var position = no_diac_text.toUpperCase().indexOf(term.toUpperCase());
- var position_with_space = no_diac_text.toUpperCase().indexOf(" " + term.toUpperCase());
- if ( (position != -1 && position === 0 ) || position_with_space != -1 ) {
- return true;
- } else {
- return false;
- }
- };
- }
- opts.formatResult = this.formatResult;
- opts.formatSearching = mw.msg( "sf-select2-searching" );
- opts.formatNoMatches = "";
- opts.placeholder = $(input_id).attr( "placeholder" );
- if ( $(input_id).attr( "existingvaluesonly" ) !== "true" && input_tagname == "INPUT" ) {
- opts.createSearchChoice = function( term, data ) { if ( $(data).filter(function() { return this.text.localeCompare( term )===0; }).length===0 ) {return { id:term, text:term };} };
- }
- if ( $(input_id).val() !== "" && input_tagname == "INPUT" ) {
- opts.initSelection = function ( element, callback ) {
- var data = [];
- var delim = self.getDelimiter($(input_id));
- var i = 0;
- $(element.val().trim().split(delim)).each(function () {
- if ( this !== "" ) {
- data.push({id: i, text: this});
- i += 1;
- }
- });
- element.val( "" );
- callback(data);
- };
- }
- var size = $(input_id).attr("size");
- if ( size === undefined ) {
- size = 100; //default value
- }
- opts.containerCss = { 'min-width': size * 6 };
- opts.containerCssClass = 'sf-select2-container';
- opts.dropdownCssClass = 'sf-select2-dropdown';
-
- opts.multiple = true;
- opts.tokenSeparators = this.getDelimiter($(input_id));
- opts.openOnEnter = true;
- var maxvalues = $(input_id).attr( "maxvalues" );
- if ( maxvalues !== undefined ) {
- opts.maximumSelectionSize = maxvalues;
- opts.formatSelectionTooBig = mw.msg( "sf-select2-selection-too-big", maxvalues );
- }
- opts.adaptContainerCssClass = function( clazz ) {
- if (clazz == "mandatoryField") {
- return "";
- } else {
- return clazz;
- }
- };
-
- return opts;
- };
- /*
- * Returns data to be used by select2 for tokens autocompletion
- *
- * @param {string} autocompletesettings
- * @return {associative array} values
- *
- */
- tokens_proto.getData = function( autocompletesettings ) {
- var input_id = "#" + this.id;
- var values = [];
- var data;
- var dep_on = this.dependentOn();
- if ( dep_on === null ) {
- if ( autocompletesettings == 'external data' ) {
- var name = $(input_id).attr(this.nameAttr($(input_id)));
- var sfgEDSettings = mw.config.get( 'sfgEDSettings' );
- var edgValues = mw.config.get( 'edgValues' );
- data = {};
- if ( sfgEDSettings[name].title !== undefined && sfgEDSettings[name].title !== "" ) {
- data.title = edgValues[sfgEDSettings[name].title];
- i = 0;
- if ( data.title !== undefined && data.title !== null ) {
- data.title.forEach(function() {
- values.push({
- id: i + 1, text: data.title[i]
- });
- i++;
- });
- }
- if ( sfgEDSettings[name].image !== undefined && sfgEDSettings[name].image !== "" ) {
- data.image = edgValues[sfgEDSettings[name].image];
- i = 0;
- if ( data.image !== undefined && data.image !== null ) {
- data.image.forEach(function() {
- values[i].image = data.image[i];
- i++;
- });
- }
- }
- if ( sfgEDSettings[name].description !== undefined && sfgEDSettings[name].description !== "" ) {
- data.description = edgValues[sfgEDSettings[name].description];
- i = 0;
- if ( data.description !== undefined && data.description !== null ) {
- data.description.forEach(function() {
- values[i].description = data.description[i];
- i++;
- });
- }
- }
- }
-
- } else {
- var sfgAutocompleteValues = mw.config.get( 'sfgAutocompleteValues' );
- data = sfgAutocompleteValues[autocompletesettings];
- var i = 0;
- //Convert data into the format accepted by Select2
- if ( data !== undefined && data !== null ) {
- data.forEach(function()
- {
- values.push({
- id: i, text: data[i]
- });
- i++;
- });
- }
- }
- } else { //Dependent field autocompletion
- var dep_field_opts = this.getDependentFieldOpts( dep_on );
- var my_server = mw.config.get( 'wgScriptPath' ) + "/api.php";
- my_server += "?action=sfautocomplete&format=json&property=" + dep_field_opts.prop + "&baseprop=" + dep_field_opts.base_prop + "&basevalue=" + dep_field_opts.base_value;
- $.ajax({
- url: my_server,
- dataType: 'json',
- async: false,
- success: function(data) {
- var id = 0;
- //Convert data into the format accepted by Select2
- data.sfautocomplete.forEach( function(item) {
- values.push({
- id: id++, text: item.title
- });
- });
- return values;
- }
- });
- }
-
- return values;
- };
- /*
- * Returns ajax options to be used by select2 for
- * remote autocompletion of tokens
- *
- * @return {object} ajaxOpts
- *
- */
- tokens_proto.getAjaxOpts = function() {
- var autocomplete_opts = this.getAutocompleteOpts();
- var data_source = autocomplete_opts.autocompletesettings.split(',')[0];
- var my_server = mw.util.wikiScript( 'api' );
- my_server += "?action=sfautocomplete&format=json&" + autocomplete_opts.autocompletedatatype + "=" + data_source;
-
- var ajaxOpts = {
- url: my_server,
- dataType: 'json',
- data: function (term) {
- return {
- substr: term, // search term
- };
- },
- results: function (data, page, query) { // parse the results into the format expected by Select2.
- var id = 0;
- if (data.sfautocomplete !== undefined) {
- data.sfautocomplete.forEach( function(item) {
- item.id = id++;
- item.text = item.title;
- });
- return {results: data.sfautocomplete};
- } else {
- return {results: []};
- }
- }
- };
-
- return ajaxOpts;
- };
- /*
- * Used to set the value of the HTMLInputElement
- * when there is a change in the select2 value
- *
- */
- tokens_proto.onChange = function() {
- var self = this;
- var data = $(this).select2( "data" );
- var tokens = new sf.select2.tokens();
- var delim = tokens.getDelimiter( $(this) );
-
- if (data !== null) {
- var tokens_value = "";
- data.forEach( function( token ) {
- tokens_value += token.text.trim() + delim + " ";
- });
- $(this).val( tokens_value );
- } else {
- $(this).val( '' );
- }
- };
- /*
- * Returns delimiter for the token field
- *
- * @return {string} delimiter
- *
- */
- tokens_proto.getDelimiter = function ( element ) {
- var field_values = element.attr('autocompletesettings').split( ',' );
- var delimiter = ",";
- if (field_values[1] == 'list' && field_values[2] !== undefined ) {
- delimiter = field_values[2];
- }
-
- return delimiter;
- };
- /*
- * Makes the choices rearrangable in tokens
- *
- * @param {HTMLElement} element
- *
- */
- tokens_proto.sortable = function( element ) {
- element.select2("container").find("ul.select2-choices").sortable({
- containment: 'parent',
- start: function() { $(".sfTokens").select2("onSortStart"); },
- update: function() { $(".sfTokens").select2("onSortEnd"); }
- });
- };
-
- sf.select2.tokens.prototype = tokens_proto;
-
-} )( jQuery, mediaWiki, semanticforms ); \ No newline at end of file
diff --git a/SemanticForms/libs/jquery.browser.js b/SemanticForms/libs/jquery.browser.js
deleted file mode 100644
index 53df7491..00000000
--- a/SemanticForms/libs/jquery.browser.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * Copy of some code from jquery.migrate.js to provide the jquery.browser functionality
- * which was removed from recent jQuery versions
- *
- * TODO: Actually remove usage of jquery.browser from SF
- *
- * @author Stephan Gambke
- */
-
-; (function (jQuery) {
- var uaMatch = function (ua) {
- ua = ua.toLowerCase();
-
- var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
- /(webkit)[ \/]([\w.]+)/.exec(ua) ||
- /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
- /(msie) ([\w.]+)/.exec(ua) ||
- ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
- [];
-
- return {
- browser: match[ 1 ] || "",
- version: match[ 2 ] || "0"
- };
- };
-
-// Don't clobber any existing jQuery.browser in case it's different
- if (!jQuery.browser) {
- var matched = uaMatch(navigator.userAgent);
- var browser = {};
-
- if (matched.browser) {
- browser[ matched.browser ] = true;
- browser.version = matched.version;
- }
-
- // Chrome is Webkit, but Webkit is also Safari.
- if (browser.chrome) {
- browser.webkit = true;
- } else if (browser.webkit) {
- browser.safari = true;
- }
-
- jQuery.browser = browser;
- }
-})( jQuery );
diff --git a/SemanticForms/libs/jquery.dynatree.js b/SemanticForms/libs/jquery.dynatree.js
deleted file mode 100644
index 308ad009..00000000
--- a/SemanticForms/libs/jquery.dynatree.js
+++ /dev/null
@@ -1,3420 +0,0 @@
-/*************************************************************************
- jquery.dynatree.js
- Dynamic tree view control, with support for lazy loading of branches.
-
- Copyright (c) 2006-2013, Martin Wendt (http://wwWendt.de)
- Dual licensed under the MIT or GPL Version 2 licenses.
- http://code.google.com/p/dynatree/wiki/LicenseInfo
-
- A current version and some documentation is available at
- http://dynatree.googlecode.com/
-
- $Version: 1.2.4$
- $Revision: 644, 2013-02-12 21:39:36$
-
- @depends: jquery.js
- @depends: jquery.ui.core.js
- @depends: jquery.cookie.js
-*************************************************************************/
-
-/* jsHint options*/
-// Note: We currently allow eval() to parse the 'data' attribtes, when initializing from HTML.
-// TODO: pass jsHint with the options given in grunt.js only.
-// The following should not be required:
-/*global alert */
-/*jshint nomen:false, smarttabs:true, eqeqeq:false, evil:true, regexp:false */
-
-/*************************************************************************
- * Debug functions
- */
-
-var _canLog = true;
-
-function _log(mode, msg) {
- /**
- * Usage: logMsg("%o was toggled", this);
- */
- if( !_canLog ){
- return;
- }
- // Remove first argument
- var args = Array.prototype.slice.apply(arguments, [1]);
- // Prepend timestamp
- var dt = new Date();
- var tag = dt.getHours()+":"+dt.getMinutes()+":"+dt.getSeconds()+"."+dt.getMilliseconds();
- args[0] = tag + " - " + args[0];
-
- try {
- switch( mode ) {
- case "info":
- window.console.info.apply(window.console, args);
- break;
- case "warn":
- window.console.warn.apply(window.console, args);
- break;
- default:
- window.console.log.apply(window.console, args);
- break;
- }
- } catch(e) {
- if( !window.console ){
- _canLog = false; // Permanently disable, when logging is not supported by the browser
- }else if(e.number === -2146827850){
- // fix for IE8, where window.console.log() exists, but does not support .apply()
- window.console.log(args.join(", "));
- }
- }
-}
-
-/* Check browser version, since $.browser was removed in jQuery 1.9 */
-function _checkBrowser(){
- var matched, browser;
- function uaMatch( ua ) {
- ua = ua.toLowerCase();
- var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
- /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
- /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
- /(msie) ([\w.]+)/.exec( ua ) ||
- ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
- [];
- return {
- browser: match[ 1 ] || "",
- version: match[ 2 ] || "0"
- };
- }
- matched = uaMatch( navigator.userAgent );
- browser = {};
- if ( matched.browser ) {
- browser[ matched.browser ] = true;
- browser.version = matched.version;
- }
- if ( browser.chrome ) {
- browser.webkit = true;
- } else if ( browser.webkit ) {
- browser.safari = true;
- }
- return browser;
-}
-var BROWSER = jQuery.browser || _checkBrowser();
-
-function logMsg(msg) {
- Array.prototype.unshift.apply(arguments, ["debug"]);
- _log.apply(this, arguments);
-}
-
-
-// Forward declaration
-var getDynaTreePersistData = null;
-
-
-
-/*************************************************************************
- * Constants
- */
-var DTNodeStatus_Error = -1;
-var DTNodeStatus_Loading = 1;
-var DTNodeStatus_Ok = 0;
-
-
-// Start of local namespace
-(function($) {
-
-/*************************************************************************
- * Common tool functions.
- */
-
-var Class = {
- create: function() {
- return function() {
- this.initialize.apply(this, arguments);
- };
- }
-};
-
-// Tool function to get dtnode from the event target:
-function getDtNodeFromElement(el) {
- alert("getDtNodeFromElement is deprecated");
- return $.ui.dynatree.getNode(el);
-/*
- var iMax = 5;
- while( el && iMax-- ) {
- if(el.dtnode) { return el.dtnode; }
- el = el.parentNode;
- }
- return null;
-*/
-}
-
-function noop() {
-}
-
-/** Compare two dotted version strings (like '10.2.3').
- * @returns {Integer} 0: v1 == v2, -1: v1 < v2, 1: v1 > v2
- */
-function versionCompare(v1, v2) {
- var v1parts = ("" + v1).split("."),
- v2parts = ("" + v2).split("."),
- minLength = Math.min(v1parts.length, v2parts.length),
- p1, p2, i;
- // Compare tuple pair-by-pair.
- for(i = 0; i < minLength; i++) {
- // Convert to integer if possible, because "8" > "10".
- p1 = parseInt(v1parts[i], 10);
- p2 = parseInt(v2parts[i], 10);
- if (isNaN(p1)){ p1 = v1parts[i]; }
- if (isNaN(p2)){ p2 = v2parts[i]; }
- if (p1 == p2) {
- continue;
- }else if (p1 > p2) {
- return 1;
- }else if (p1 < p2) {
- return -1;
- }
- // one operand is NaN
- return NaN;
- }
- // The longer tuple is always considered 'greater'
- if (v1parts.length === v2parts.length) {
- return 0;
- }
- return (v1parts.length < v2parts.length) ? -1 : 1;
-}
-
-
-/*************************************************************************
- * Class DynaTreeNode
- */
-var DynaTreeNode = Class.create();
-
-DynaTreeNode.prototype = {
- initialize: function(parent, tree, data) {
- /**
- * @constructor
- */
- this.parent = parent;
- this.tree = tree;
- if ( typeof data === "string" ){
- data = { title: data };
- }
- if( !data.key ){
- data.key = "_" + tree._nodeCount++;
- }else{
- data.key = "" + data.key; // issue 371
- }
- this.data = $.extend({}, $.ui.dynatree.nodedatadefaults, data);
- this.li = null; // not yet created
- this.span = null; // not yet created
- this.ul = null; // not yet created
- this.childList = null; // no subnodes yet
- this._isLoading = false; // Lazy content is being loaded
- this.hasSubSel = false;
- this.bExpanded = false;
- this.bSelected = false;
-
- },
-
- toString: function() {
- return "DynaTreeNode<" + this.data.key + ">: '" + this.data.title + "'";
- },
-
- toDict: function(recursive, callback) {
- var dict = $.extend({}, this.data);
- dict.activate = ( this.tree.activeNode === this );
- dict.focus = ( this.tree.focusNode === this );
- dict.expand = this.bExpanded;
- dict.select = this.bSelected;
- if( callback ){
- callback(dict);
- }
- if( recursive && this.childList ) {
- dict.children = [];
- for(var i=0, l=this.childList.length; i<l; i++ ){
- dict.children.push(this.childList[i].toDict(true, callback));
- }
- } else {
- delete dict.children;
- }
- return dict;
- },
-
- fromDict: function(dict) {
- /**
- * Update node data. If dict contains 'children', then also replace
- * the hole sub tree.
- */
- var children = dict.children;
- if(children === undefined){
- this.data = $.extend(this.data, dict);
- this.render();
- return;
- }
- dict = $.extend({}, dict);
- dict.children = undefined;
- this.data = $.extend(this.data, dict);
- this.removeChildren();
- this.addChild(children);
- },
-
- _getInnerHtml: function() {
- var tree = this.tree,
- opts = tree.options,
- cache = tree.cache,
- level = this.getLevel(),
- data = this.data,
- res = "",
- imageSrc;
- // connector (expanded, expandable or simple)
- if( level < opts.minExpandLevel ) {
- if(level > 1){
- res += cache.tagConnector;
- }
- // .. else (i.e. for root level) skip expander/connector altogether
- } else if( this.hasChildren() !== false ) {
- res += cache.tagExpander;
- } else {
- res += cache.tagConnector;
- }
- // Checkbox mode
- if( opts.checkbox && data.hideCheckbox !== true && !data.isStatusNode ) {
- res += cache.tagCheckbox;
- }
- // folder or doctype icon
- if ( data.icon ) {
- if (data.icon.charAt(0) === "/"){
- imageSrc = data.icon;
- }else{
- imageSrc = opts.imagePath + data.icon;
- }
- res += "<img src='" + imageSrc + "' alt='' />";
- } else if ( data.icon === false ) {
- // icon == false means 'no icon'
-// noop(); // keep JSLint happy
- } else if ( data.iconClass ) {
- res += "<span class='" + " " + data.iconClass + "'></span>";
- } else {
- // icon == null means 'default icon'
- res += cache.tagNodeIcon;
- }
- // node title
- var nodeTitle = "";
- if ( opts.onCustomRender ){
- nodeTitle = opts.onCustomRender.call(tree, this) || "";
- }
- if(!nodeTitle){
- var tooltip = data.tooltip ? ' title="' + data.tooltip.replace(/\"/g, '&quot;') + '"' : '',
- href = data.href || "#";
- if( opts.noLink || data.noLink ) {
- nodeTitle = '<span style="display:inline-block;" class="' + opts.classNames.title + '"' + tooltip + '>' + data.title + '</span>';
-// this.tree.logDebug("nodeTitle: " + nodeTitle);
- } else {
- nodeTitle = '<a href="' + href + '" class="' + opts.classNames.title + '"' + tooltip + '>' + data.title + '</a>';
- }
- }
- res += nodeTitle;
- return res;
- },
-
-
- _fixOrder: function() {
- /**
- * Make sure, that <li> order matches childList order.
- */
- var cl = this.childList;
- if( !cl || !this.ul ){
- return;
- }
- var childLI = this.ul.firstChild;
- for(var i=0, l=cl.length-1; i<l; i++) {
- var childNode1 = cl[i];
- var childNode2 = childLI.dtnode;
- if( childNode1 !== childNode2 ) {
- this.tree.logDebug("_fixOrder: mismatch at index " + i + ": " + childNode1 + " != " + childNode2);
- this.ul.insertBefore(childNode1.li, childNode2.li);
- } else {
- childLI = childLI.nextSibling;
- }
- }
- },
-
-
- render: function(useEffects, includeInvisible) {
- /**
- * Create <li><span>..</span> .. </li> tags for this node.
- *
- * <li id='KEY' dtnode=NODE> // This div contains the node's span and list of child div's.
- * <span class='title'>S S S A</span> // Span contains graphic spans and title <a> tag
- * <ul> // only present, when node has children
- * <li id='KEY' dtnode=NODE>child1</li>
- * <li id='KEY' dtnode=NODE>child2</li>
- * </ul>
- * </li>
- */
-// this.tree.logDebug("%s.render(%s)", this, useEffects);
- // ---
- var tree = this.tree,
- parent = this.parent,
- data = this.data,
- opts = tree.options,
- cn = opts.classNames,
- isLastSib = this.isLastSibling(),
- firstTime = false;
-
- if( !parent && !this.ul ) {
- // Root node has only a <ul>
- this.li = this.span = null;
- this.ul = document.createElement("ul");
- if( opts.minExpandLevel > 1 ){
- this.ul.className = cn.container + " " + cn.noConnector;
- }else{
- this.ul.className = cn.container;
- }
- } else if( parent ) {
- // Create <li><span /> </li>
- if( ! this.li ) {
- firstTime = true;
- this.li = document.createElement("li");
- this.li.dtnode = this;
- if( data.key && opts.generateIds ){
- this.li.id = opts.idPrefix + data.key;
- }
- this.span = document.createElement("span");
- this.span.className = cn.title;
- this.li.appendChild(this.span);
-
- if( !parent.ul ) {
- // This is the parent's first child: create UL tag
- // (Hidden, because it will be
- parent.ul = document.createElement("ul");
- parent.ul.style.display = "none";
- parent.li.appendChild(parent.ul);
-// if( opts.minExpandLevel > this.getLevel() ){
-// parent.ul.className = cn.noConnector;
-// }
- }
- // set node connector images, links and text
-// this.span.innerHTML = this._getInnerHtml();
-
- parent.ul.appendChild(this.li);
- }
- // set node connector images, links and text
- this.span.innerHTML = this._getInnerHtml();
- // Set classes for current status
- var cnList = [];
- cnList.push(cn.node);
- if( data.isFolder ){
- cnList.push(cn.folder);
- }
- if( this.bExpanded ){
- cnList.push(cn.expanded);
- }
- if( this.hasChildren() !== false ){
- cnList.push(cn.hasChildren);
- }
- if( data.isLazy && this.childList === null ){
- cnList.push(cn.lazy);
- }
- if( isLastSib ){
- cnList.push(cn.lastsib);
- }
- if( this.bSelected ){
- cnList.push(cn.selected);
- }
- if( this.hasSubSel ){
- cnList.push(cn.partsel);
- }
- if( tree.activeNode === this ){
- cnList.push(cn.active);
- }
- if( data.addClass ){
- cnList.push(data.addClass);
- }
- // IE6 doesn't correctly evaluate multiple class names,
- // so we create combined class names that can be used in the CSS
- cnList.push(cn.combinedExpanderPrefix + (this.bExpanded ? "e" : "c") + (data.isLazy && this.childList === null ? "d" : "") + (isLastSib ? "l" : ""));
- cnList.push(cn.combinedIconPrefix + (this.bExpanded ? "e" : "c") + (data.isFolder ? "f" : ""));
- this.span.className = cnList.join(" ");
-
- // TODO: we should not set this in the <span> tag also, if we set it here:
- this.li.className = isLastSib ? cn.lastsib : "";
-
- // Allow tweaking, binding, after node was created for the first time
- if(firstTime && opts.onCreate){
- opts.onCreate.call(tree, this, this.span);
- }
- // Hide children, if node is collapsed
-// this.ul.style.display = ( this.bExpanded || !parent ) ? "" : "none";
- // Allow tweaking after node state was rendered
- if(opts.onRender){
- opts.onRender.call(tree, this, this.span);
- }
- }
- // Visit child nodes
- if( (this.bExpanded || includeInvisible === true) && this.childList ) {
- for(var i=0, l=this.childList.length; i<l; i++) {
- this.childList[i].render(false, includeInvisible);
- }
- // Make sure the tag order matches the child array
- this._fixOrder();
- }
- // Hide children, if node is collapsed
- if( this.ul ) {
- var isHidden = (this.ul.style.display === "none");
- var isExpanded = !!this.bExpanded;
-// logMsg("isHidden:%s", isHidden);
- if( useEffects && opts.fx && (isHidden === isExpanded) ) {
- var duration = opts.fx.duration || 200;
- $(this.ul).animate(opts.fx, duration);
- } else {
- this.ul.style.display = ( this.bExpanded || !parent ) ? "" : "none";
- }
- }
- },
- /** Return '/id1/id2/id3'. */
- getKeyPath: function(excludeSelf) {
- var path = [];
- this.visitParents(function(node){
- if(node.parent){
- path.unshift(node.data.key);
- }
- }, !excludeSelf);
- return "/" + path.join(this.tree.options.keyPathSeparator);
- },
-
- getParent: function() {
- return this.parent;
- },
-
- getChildren: function() {
- if(this.hasChildren() === undefined){
- return undefined; // Lazy node: unloaded, currently loading, or load error
- }
- return this.childList;
- },
-
- /** Check if node has children (returns undefined, if not sure). */
- hasChildren: function() {
- if(this.data.isLazy){
- if(this.childList === null || this.childList === undefined){
- // Not yet loaded
- return undefined;
- }else if(this.childList.length === 0){
- // Loaded, but response was empty
- return false;
- }else if(this.childList.length === 1 && this.childList[0].isStatusNode()){
- // Currently loading or load error
- return undefined;
- }
- return true;
- }
- return !!this.childList;
- },
-
- isFirstSibling: function() {
- var p = this.parent;
- return !p || p.childList[0] === this;
- },
-
- isLastSibling: function() {
- var p = this.parent;
- return !p || p.childList[p.childList.length-1] === this;
- },
-
- isLoading: function() {
- return !!this._isLoading;
- },
-
- getPrevSibling: function() {
- if( !this.parent ){
- return null;
- }
- var ac = this.parent.childList;
- for(var i=1, l=ac.length; i<l; i++){ // start with 1, so prev(first) = null
- if( ac[i] === this ){
- return ac[i-1];
- }
- }
- return null;
- },
-
- getNextSibling: function() {
- if( !this.parent ){
- return null;
- }
- var ac = this.parent.childList;
- for(var i=0, l=ac.length-1; i<l; i++){ // up to length-2, so next(last) = null
- if( ac[i] === this ){
- return ac[i+1];
- }
- }
- return null;
- },
-
- isStatusNode: function() {
- return (this.data.isStatusNode === true);
- },
-
- isChildOf: function(otherNode) {
- return (this.parent && this.parent === otherNode);
- },
-
- isDescendantOf: function(otherNode) {
- if(!otherNode){
- return false;
- }
- var p = this.parent;
- while( p ) {
- if( p === otherNode ){
- return true;
- }
- p = p.parent;
- }
- return false;
- },
-
- countChildren: function() {
- var cl = this.childList;
- if( !cl ){
- return 0;
- }
- var n = cl.length;
- for(var i=0, l=n; i<l; i++){
- var child = cl[i];
- n += child.countChildren();
- }
- return n;
- },
-
- /**Sort child list by title.
- * cmd: optional compare function.
- * deep: optional: pass true to sort all descendant nodes.
- */
- sortChildren: function(cmp, deep) {
- var cl = this.childList;
- if( !cl ){
- return;
- }
- cmp = cmp || function(a, b) {
-// return a.data.title === b.data.title ? 0 : a.data.title > b.data.title ? 1 : -1;
- var x = a.data.title.toLowerCase(),
- y = b.data.title.toLowerCase();
- return x === y ? 0 : x > y ? 1 : -1;
- };
- cl.sort(cmp);
- if( deep ){
- for(var i=0, l=cl.length; i<l; i++){
- if( cl[i].childList ){
- cl[i].sortChildren(cmp, "$norender$");
- }
- }
- }
- if( deep !== "$norender$" ){
- this.render();
- }
- },
-
- _setStatusNode: function(data) {
- // Create, modify or remove the status child node (pass 'null', to remove it).
- var firstChild = ( this.childList ? this.childList[0] : null );
- if( !data ) {
- if ( firstChild && firstChild.isStatusNode()) {
- try{
- // I've seen exceptions here with loadKeyPath...
- if(this.ul){
- this.ul.removeChild(firstChild.li);
- firstChild.li = null; // avoid leaks (issue 215)
- }
- }catch(e){}
- if( this.childList.length === 1 ){
- this.childList = [];
- }else{
- this.childList.shift();
- }
- }
- } else if ( firstChild ) {
- data.isStatusNode = true;
- data.key = "_statusNode";
- firstChild.data = data;
- firstChild.render();
- } else {
- data.isStatusNode = true;
- data.key = "_statusNode";
- firstChild = this.addChild(data);
- }
- },
-
- setLazyNodeStatus: function(lts, opts) {
- var tooltip = (opts && opts.tooltip) ? opts.tooltip : null,
- info = (opts && opts.info) ? " (" + opts.info + ")" : "";
- switch( lts ) {
- case DTNodeStatus_Ok:
- this._setStatusNode(null);
- $(this.span).removeClass(this.tree.options.classNames.nodeLoading);
- this._isLoading = false;
-// this.render();
- if( this.tree.options.autoFocus ) {
- if( this === this.tree.tnRoot && this.childList && this.childList.length > 0) {
- // special case: using ajaxInit
- this.childList[0].focus();
- } else {
- this.focus();
- }
- }
- break;
- case DTNodeStatus_Loading:
- this._isLoading = true;
- $(this.span).addClass(this.tree.options.classNames.nodeLoading);
- // The root is hidden, so we set a temporary status child
- if(!this.parent){
- this._setStatusNode({
- title: this.tree.options.strings.loading + info,
- tooltip: tooltip,
- addClass: this.tree.options.classNames.nodeWait
- });
- }
- break;
- case DTNodeStatus_Error:
- this._isLoading = false;
-// $(this.span).addClass(this.tree.options.classNames.nodeError);
- this._setStatusNode({
- title: this.tree.options.strings.loadError + info,
- tooltip: tooltip,
- addClass: this.tree.options.classNames.nodeError
- });
- break;
- default:
- throw "Bad LazyNodeStatus: '" + lts + "'.";
- }
- },
-
- _parentList: function(includeRoot, includeSelf) {
- var l = [];
- var dtn = includeSelf ? this : this.parent;
- while( dtn ) {
- if( includeRoot || dtn.parent ){
- l.unshift(dtn);
- }
- dtn = dtn.parent;
- }
- return l;
- },
- getLevel: function() {
- /**
- * Return node depth. 0: System root node, 1: visible top-level node.
- */
- var level = 0;
- var dtn = this.parent;
- while( dtn ) {
- level++;
- dtn = dtn.parent;
- }
- return level;
- },
-
- _getTypeForOuterNodeEvent: function(event) {
- /** Return the inner node span (title, checkbox or expander) if
- * event.target points to the outer span.
- * This function should fix issue #93:
- * FF2 ignores empty spans, when generating events (returning the parent instead).
- */
- var cns = this.tree.options.classNames;
- var target = event.target;
- // Only process clicks on an outer node span (probably due to a FF2 event handling bug)
- if( target.className.indexOf(cns.node) < 0 ) {
- return null;
- }
- // Event coordinates, relative to outer node span:
- var eventX = event.pageX - target.offsetLeft;
- var eventY = event.pageY - target.offsetTop;
-
- for(var i=0, l=target.childNodes.length; i<l; i++) {
- var cn = target.childNodes[i];
- var x = cn.offsetLeft - target.offsetLeft;
- var y = cn.offsetTop - target.offsetTop;
- var nx = cn.clientWidth, ny = cn.clientHeight;
-// alert (cn.className + ": " + x + ", " + y + ", s:" + nx + ", " + ny);
- if( eventX >= x && eventX <= (x+nx) && eventY >= y && eventY <= (y+ny) ) {
-// alert("HIT "+ cn.className);
- if( cn.className==cns.title ){
- return "title";
- }else if( cn.className==cns.expander ){
- return "expander";
- }else if( cn.className==cns.checkbox ){
- return "checkbox";
- }else if( cn.className==cns.nodeIcon ){
- return "icon";
- }
- }
- }
- return "prefix";
- },
-
- getEventTargetType: function(event) {
- // Return the part of a node, that a click event occured on.
- // Note: there is no check, if the event was fired on THIS node.
- var tcn = event && event.target ? event.target.className : "",
- cns = this.tree.options.classNames;
-
- if( tcn === cns.title ){
- return "title";
- }else if( tcn === cns.expander ){
- return "expander";
- }else if( tcn === cns.checkbox ){
- return "checkbox";
- }else if( tcn === cns.nodeIcon ){
- return "icon";
- }else if( tcn === cns.empty || tcn === cns.vline || tcn === cns.connector ){
- return "prefix";
- }else if( tcn.indexOf(cns.node) >= 0 ){
- // FIX issue #93
- return this._getTypeForOuterNodeEvent(event);
- }
- return null;
- },
-
- isVisible: function() {
- // Return true, if all parents are expanded.
- var parents = this._parentList(true, false);
- for(var i=0, l=parents.length; i<l; i++){
- if( ! parents[i].bExpanded ){ return false; }
- }
- return true;
- },
-
- makeVisible: function() {
- // Make sure, all parents are expanded
- var parents = this._parentList(true, false);
- for(var i=0, l=parents.length; i<l; i++){
- parents[i]._expand(true);
- }
- },
-
- focus: function() {
- // TODO: check, if we already have focus
-// this.tree.logDebug("dtnode.focus(): %o", this);
- this.makeVisible();
- try {
- $(this.span).find(">a").focus();
- } catch(e) { }
- },
-
- isFocused: function() {
- return (this.tree.tnFocused === this);
- },
-
- _activate: function(flag, fireEvents) {
- // (De)Activate - but not focus - this node.
- this.tree.logDebug("dtnode._activate(%o, fireEvents=%o) - %o", flag, fireEvents, this);
- var opts = this.tree.options;
- if( this.data.isStatusNode ){
- return;
- }
- if ( fireEvents && opts.onQueryActivate && opts.onQueryActivate.call(this.tree, flag, this) === false ){
- return; // Callback returned false
- }
- if( flag ) {
- // Activate
- if( this.tree.activeNode ) {
- if( this.tree.activeNode === this ){
- return;
- }
- this.tree.activeNode.deactivate();
- }
- if( opts.activeVisible ){
- this.makeVisible();
- }
- this.tree.activeNode = this;
- if( opts.persist ){
- $.cookie(opts.cookieId+"-active", this.data.key, opts.cookie);
- }
- this.tree.persistence.activeKey = this.data.key;
- $(this.span).addClass(opts.classNames.active);
- if ( fireEvents && opts.onActivate ){
- opts.onActivate.call(this.tree, this);
- }
- } else {
- // Deactivate
- if( this.tree.activeNode === this ) {
- if ( opts.onQueryActivate && opts.onQueryActivate.call(this.tree, false, this) === false ){
- return; // Callback returned false
- }
- $(this.span).removeClass(opts.classNames.active);
- if( opts.persist ) {
- // Note: we don't pass null, but ''. So the cookie is not deleted.
- // If we pass null, we also have to pass a COPY of opts, because $cookie will override opts.expires (issue 84)
- $.cookie(opts.cookieId+"-active", "", opts.cookie);
- }
- this.tree.persistence.activeKey = null;
- this.tree.activeNode = null;
- if ( fireEvents && opts.onDeactivate ){
- opts.onDeactivate.call(this.tree, this);
- }
- }
- }
- },
-
- activate: function() {
- // Select - but not focus - this node.
-// this.tree.logDebug("dtnode.activate(): %o", this);
- this._activate(true, true);
- },
-
- activateSilently: function() {
- this._activate(true, false);
- },
-
- deactivate: function() {
-// this.tree.logDebug("dtnode.deactivate(): %o", this);
- this._activate(false, true);
- },
-
- isActive: function() {
- return (this.tree.activeNode === this);
- },
-
- _userActivate: function() {
- // Handle user click / [space] / [enter], according to clickFolderMode.
- var activate = true;
- var expand = false;
- if ( this.data.isFolder ) {
- switch( this.tree.options.clickFolderMode ) {
- case 2:
- activate = false;
- expand = true;
- break;
- case 3:
- activate = expand = true;
- break;
- }
- }
- if( this.parent === null ) {
- expand = false;
- }
- if( expand ) {
- this.toggleExpand();
- this.focus();
- }
- if( activate ) {
- this.activate();
- }
- },
-
- _setSubSel: function(hasSubSel) {
- if( hasSubSel ) {
- this.hasSubSel = true;
- $(this.span).addClass(this.tree.options.classNames.partsel);
- } else {
- this.hasSubSel = false;
- $(this.span).removeClass(this.tree.options.classNames.partsel);
- }
- },
- /**
- * Fix selection and partsel status, of parent nodes, according to current status of
- * end nodes.
- */
- _updatePartSelectionState: function() {
-// alert("_updatePartSelectionState " + this);
-// this.tree.logDebug("_updatePartSelectionState() - %o", this);
- var sel;
- // Return `true` or `false` for end nodes and remove part-sel flag
- if( ! this.hasChildren() ){
- sel = (this.bSelected && !this.data.unselectable && !this.data.isStatusNode);
- this._setSubSel(false);
- return sel;
- }
- // Return `true`, `false`, or `undefined` for parent nodes
- var i, l,
- cl = this.childList,
- allSelected = true,
- allDeselected = true;
- for(i=0, l=cl.length; i<l; i++) {
- var n = cl[i],
- s = n._updatePartSelectionState();
- if( s !== false){
- allDeselected = false;
- }
- if( s !== true){
- allSelected = false;
- }
- }
- if( allSelected ){
- sel = true;
- } else if ( allDeselected ){
- sel = false;
- } else {
- sel = undefined;
- }
- this._setSubSel(sel === undefined);
- this.bSelected = (sel === true);
- return sel;
- },
-
- /**
- * Fix selection status, after this node was (de)selected in multi-hier mode.
- * This includes (de)selecting all children.
- */
- _fixSelectionState: function() {
-// alert("_fixSelectionState " + this);
-// this.tree.logDebug("_fixSelectionState(%s) - %o", this.bSelected, this);
- var p, i, l;
- if( this.bSelected ) {
- // Select all children
- this.visit(function(node){
- node.parent._setSubSel(true);
- if(!node.data.unselectable){
- node._select(true, false, false);
- }
- });
- // Select parents, if all children are selected
- p = this.parent;
- while( p ) {
- p._setSubSel(true);
- var allChildsSelected = true;
- for(i=0, l=p.childList.length; i<l; i++) {
- var n = p.childList[i];
- if( !n.bSelected && !n.data.isStatusNode && !n.data.unselectable) {
- // issue 305 proposes this:
-// if( !n.bSelected && !n.data.isStatusNode ) {
- allChildsSelected = false;
- break;
- }
- }
- if( allChildsSelected ){
- p._select(true, false, false);
- }
- p = p.parent;
- }
- } else {
- // Deselect all children
- this._setSubSel(false);
- this.visit(function(node){
- node._setSubSel(false);
- node._select(false, false, false);
- });
- // Deselect parents, and recalc hasSubSel
- p = this.parent;
- while( p ) {
- p._select(false, false, false);
- var isPartSel = false;
- for(i=0, l=p.childList.length; i<l; i++) {
- if( p.childList[i].bSelected || p.childList[i].hasSubSel ) {
- isPartSel = true;
- break;
- }
- }
- p._setSubSel(isPartSel);
- p = p.parent;
- }
- }
- },
-
- _select: function(sel, fireEvents, deep) {
- // Select - but not focus - this node.
-// this.tree.logDebug("dtnode._select(%o) - %o", sel, this);
- var opts = this.tree.options;
- if( this.data.isStatusNode ){
- return;
- }
- //
- if( this.bSelected === sel ) {
-// this.tree.logDebug("dtnode._select(%o) IGNORED - %o", sel, this);
- return;
- }
- // Allow event listener to abort selection
- if ( fireEvents && opts.onQuerySelect && opts.onQuerySelect.call(this.tree, sel, this) === false ){
- return; // Callback returned false
- }
- // Force single-selection
- if( opts.selectMode==1 && sel ) {
- this.tree.visit(function(node){
- if( node.bSelected ) {
- // Deselect; assuming that in selectMode:1 there's max. one other selected node
- node._select(false, false, false);
- return false;
- }
- });
- }
-
- this.bSelected = sel;
-// this.tree._changeNodeList("select", this, sel);
-
- if( sel ) {
- if( opts.persist ){
- this.tree.persistence.addSelect(this.data.key);
- }
- $(this.span).addClass(opts.classNames.selected);
-
- if( deep && opts.selectMode === 3 ){
- this._fixSelectionState();
- }
- if ( fireEvents && opts.onSelect ){
- opts.onSelect.call(this.tree, true, this);
- }
- } else {
- if( opts.persist ){
- this.tree.persistence.clearSelect(this.data.key);
- }
- $(this.span).removeClass(opts.classNames.selected);
-
- if( deep && opts.selectMode === 3 ){
- this._fixSelectionState();
- }
- if ( fireEvents && opts.onSelect ){
- opts.onSelect.call(this.tree, false, this);
- }
- }
- },
-
- select: function(sel) {
- // Select - but not focus - this node.
-// this.tree.logDebug("dtnode.select(%o) - %o", sel, this);
- if( this.data.unselectable ){
- return this.bSelected;
- }
- return this._select(sel!==false, true, true);
- },
-
- toggleSelect: function() {
-// this.tree.logDebug("dtnode.toggleSelect() - %o", this);
- return this.select(!this.bSelected);
- },
-
- isSelected: function() {
- return this.bSelected;
- },
-
- isLazy: function() {
- return !!this.data.isLazy;
- },
-
- _loadContent: function() {
- try {
- var opts = this.tree.options;
- this.tree.logDebug("_loadContent: start - %o", this);
- this.setLazyNodeStatus(DTNodeStatus_Loading);
- if( true === opts.onLazyRead.call(this.tree, this) ) {
- // If function returns 'true', we assume that the loading is done:
- this.setLazyNodeStatus(DTNodeStatus_Ok);
- // Otherwise (i.e. if the loading was started as an asynchronous process)
- // the onLazyRead(dtnode) handler is expected to call dtnode.setLazyNodeStatus(DTNodeStatus_Ok/_Error) when done.
- this.tree.logDebug("_loadContent: succeeded - %o", this);
- }
- } catch(e) {
- this.tree.logWarning("_loadContent: failed - %o", e);
- this.setLazyNodeStatus(DTNodeStatus_Error, {tooltip: ""+e});
- }
- },
-
- _expand: function(bExpand, forceSync) {
- if( this.bExpanded === bExpand ) {
- this.tree.logDebug("dtnode._expand(%o) IGNORED - %o", bExpand, this);
- return;
- }
- this.tree.logDebug("dtnode._expand(%o) - %o", bExpand, this);
- var opts = this.tree.options;
- if( !bExpand && this.getLevel() < opts.minExpandLevel ) {
- this.tree.logDebug("dtnode._expand(%o) prevented collapse - %o", bExpand, this);
- return;
- }
- if ( opts.onQueryExpand && opts.onQueryExpand.call(this.tree, bExpand, this) === false ){
- return; // Callback returned false
- }
- this.bExpanded = bExpand;
-
- // Persist expand state
- if( opts.persist ) {
- if( bExpand ){
- this.tree.persistence.addExpand(this.data.key);
- }else{
- this.tree.persistence.clearExpand(this.data.key);
- }
- }
- // Do not apply animations in init phase, or before lazy-loading
- var allowEffects = !(this.data.isLazy && this.childList === null) && !this._isLoading && !forceSync;
- this.render(allowEffects);
-
- // Auto-collapse mode: collapse all siblings
- if( this.bExpanded && this.parent && opts.autoCollapse ) {
- var parents = this._parentList(false, true);
- for(var i=0, l=parents.length; i<l; i++){
- parents[i].collapseSiblings();
- }
- }
- // If the currently active node is now hidden, deactivate it
- if( opts.activeVisible && this.tree.activeNode && ! this.tree.activeNode.isVisible() ) {
- this.tree.activeNode.deactivate();
- }
- // Expanding a lazy node: set 'loading...' and call callback
- if( bExpand && this.data.isLazy && this.childList === null && !this._isLoading ) {
- this._loadContent();
- return;
- }
- if ( opts.onExpand ){
- opts.onExpand.call(this.tree, bExpand, this);
- }
- },
-
- isExpanded: function() {
- return this.bExpanded;
- },
-
- expand: function(flag) {
- flag = (flag !== false);
- if( !this.childList && !this.data.isLazy && flag ){
- return; // Prevent expanding empty nodes
- } else if( this.parent === null && !flag ){
- return; // Prevent collapsing the root
- }
- this._expand(flag);
- },
-
- scheduleAction: function(mode, ms) {
- /** Schedule activity for delayed execution (cancel any pending request).
- * scheduleAction('cancel') will cancel the request.
- */
- if( this.tree.timer ) {
- clearTimeout(this.tree.timer);
- this.tree.logDebug("clearTimeout(%o)", this.tree.timer);
- }
- var self = this; // required for closures
- switch (mode) {
- case "cancel":
- // Simply made sure that timer was cleared
- break;
- case "expand":
- this.tree.timer = setTimeout(function(){
- self.tree.logDebug("setTimeout: trigger expand");
- self.expand(true);
- }, ms);
- break;
- case "activate":
- this.tree.timer = setTimeout(function(){
- self.tree.logDebug("setTimeout: trigger activate");
- self.activate();
- }, ms);
- break;
- default:
- throw "Invalid mode " + mode;
- }
- this.tree.logDebug("setTimeout(%s, %s): %s", mode, ms, this.tree.timer);
- },
-
- toggleExpand: function() {
- this.expand(!this.bExpanded);
- },
-
- collapseSiblings: function() {
- if( this.parent === null ){
- return;
- }
- var ac = this.parent.childList;
- for (var i=0, l=ac.length; i<l; i++) {
- if ( ac[i] !== this && ac[i].bExpanded ){
- ac[i]._expand(false);
- }
- }
- },
-
- _onClick: function(event) {
-// this.tree.logDebug("dtnode.onClick(" + event.type + "): dtnode:" + this + ", button:" + event.button + ", which: " + event.which);
- var targetType = this.getEventTargetType(event);
- if( targetType === "expander" ) {
- // Clicking the expander icon always expands/collapses
- this.toggleExpand();
- this.focus(); // issue 95
- } else if( targetType === "checkbox" ) {
- // Clicking the checkbox always (de)selects
- this.toggleSelect();
- this.focus(); // issue 95
- } else {
- this._userActivate();
- var aTag = this.span.getElementsByTagName("a");
- if(aTag[0]){
- // issue 154, 313
-// if(!($.browser.msie && parseInt($.browser.version, 10) < 9)){
- if(!(BROWSER.msie && parseInt(BROWSER.version, 10) < 9)){
- aTag[0].focus();
- }
- }else{
- // 'noLink' option was set
- return true;
- }
- }
- // Make sure that clicks stop, otherwise <a href='#'> jumps to the top
- event.preventDefault();
- },
-
- _onDblClick: function(event) {
-// this.tree.logDebug("dtnode.onDblClick(" + event.type + "): dtnode:" + this + ", button:" + event.button + ", which: " + event.which);
- },
-
- _onKeydown: function(event) {
-// this.tree.logDebug("dtnode.onKeydown(" + event.type + "): dtnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
- var handled = true,
- sib;
-// alert("keyDown" + event.which);
-
- switch( event.which ) {
- // charCodes:
-// case 43: // '+'
- case 107: // '+'
- case 187: // '+' @ Chrome, Safari
- if( !this.bExpanded ){ this.toggleExpand(); }
- break;
-// case 45: // '-'
- case 109: // '-'
- case 189: // '+' @ Chrome, Safari
- if( this.bExpanded ){ this.toggleExpand(); }
- break;
- //~ case 42: // '*'
- //~ break;
- //~ case 47: // '/'
- //~ break;
- // case 13: // <enter>
- // <enter> on a focused <a> tag seems to generate a click-event.
- // this._userActivate();
- // break;
- case 32: // <space>
- this._userActivate();
- break;
- case 8: // <backspace>
- if( this.parent ){
- this.parent.focus();
- }
- break;
- case 37: // <left>
- if( this.bExpanded ) {
- this.toggleExpand();
- this.focus();
-// } else if( this.parent && (this.tree.options.rootVisible || this.parent.parent) ) {
- } else if( this.parent && this.parent.parent ) {
- this.parent.focus();
- }
- break;
- case 39: // <right>
- if( !this.bExpanded && (this.childList || this.data.isLazy) ) {
- this.toggleExpand();
- this.focus();
- } else if( this.childList ) {
- this.childList[0].focus();
- }
- break;
- case 38: // <up>
- sib = this.getPrevSibling();
- while( sib && sib.bExpanded && sib.childList ){
- sib = sib.childList[sib.childList.length-1];
- }
-// if( !sib && this.parent && (this.tree.options.rootVisible || this.parent.parent) )
- if( !sib && this.parent && this.parent.parent ){
- sib = this.parent;
- }
- if( sib ){
- sib.focus();
- }
- break;
- case 40: // <down>
- if( this.bExpanded && this.childList ) {
- sib = this.childList[0];
- } else {
- var parents = this._parentList(false, true);
- for(var i=parents.length-1; i>=0; i--) {
- sib = parents[i].getNextSibling();
- if( sib ){ break; }
- }
- }
- if( sib ){
- sib.focus();
- }
- break;
- default:
- handled = false;
- }
- // Return false, if handled, to prevent default processing
-// return !handled;
- if(handled){
- event.preventDefault();
- }
- },
-
- _onKeypress: function(event) {
- // onKeypress is only hooked to allow user callbacks.
- // We don't process it, because IE and Safari don't fire keypress for cursor keys.
-// this.tree.logDebug("dtnode.onKeypress(" + event.type + "): dtnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
- },
-
- _onFocus: function(event) {
- // Handles blur and focus events.
-// this.tree.logDebug("dtnode._onFocus(%o): %o", event, this);
- var opts = this.tree.options;
- if ( event.type == "blur" || event.type == "focusout" ) {
- if ( opts.onBlur ){
- opts.onBlur.call(this.tree, this);
- }
- if( this.tree.tnFocused ){
- $(this.tree.tnFocused.span).removeClass(opts.classNames.focused);
- }
- this.tree.tnFocused = null;
- if( opts.persist ){
- $.cookie(opts.cookieId+"-focus", "", opts.cookie);
- }
- } else if ( event.type=="focus" || event.type=="focusin") {
- // Fix: sometimes the blur event is not generated
- if( this.tree.tnFocused && this.tree.tnFocused !== this ) {
- this.tree.logDebug("dtnode.onFocus: out of sync: curFocus: %o", this.tree.tnFocused);
- $(this.tree.tnFocused.span).removeClass(opts.classNames.focused);
- }
- this.tree.tnFocused = this;
- if ( opts.onFocus ){
- opts.onFocus.call(this.tree, this);
- }
- $(this.tree.tnFocused.span).addClass(opts.classNames.focused);
- if( opts.persist ){
- $.cookie(opts.cookieId+"-focus", this.data.key, opts.cookie);
- }
- }
- // TODO: return anything?
-// return false;
- },
-
- visit: function(fn, includeSelf) {
- // Call fn(node) for all child nodes. Stop iteration, if fn() returns false.
- var res = true;
- if( includeSelf === true ) {
- res = fn(this);
- if( res === false || res == "skip" ){
- return res;
- }
- }
- if(this.childList){
- for(var i=0, l=this.childList.length; i<l; i++){
- res = this.childList[i].visit(fn, true);
- if( res === false ){
- break;
- }
- }
- }
- return res;
- },
-
- visitParents: function(fn, includeSelf) {
- // Visit parent nodes (bottom up)
- if(includeSelf && fn(this) === false){
- return false;
- }
- var p = this.parent;
- while( p ) {
- if(fn(p) === false){
- return false;
- }
- p = p.parent;
- }
- return true;
- },
-
- remove: function() {
- // Remove this node
-// this.tree.logDebug ("%s.remove()", this);
- if ( this === this.tree.root ){
- throw "Cannot remove system root";
- }
- return this.parent.removeChild(this);
- },
-
- removeChild: function(tn) {
- // Remove tn from list of direct children.
- var ac = this.childList;
- if( ac.length == 1 ) {
- if( tn !== ac[0] ){
- throw "removeChild: invalid child";
- }
- return this.removeChildren();
- }
- if( tn === this.tree.activeNode ){
- tn.deactivate();
- }
- if( this.tree.options.persist ) {
- if( tn.bSelected ){
- this.tree.persistence.clearSelect(tn.data.key);
- }
- if ( tn.bExpanded ){
- this.tree.persistence.clearExpand(tn.data.key);
- }
- }
- tn.removeChildren(true);
- if(this.ul){
-// $("li", $(this.ul)).remove(); // issue 399
- this.ul.removeChild(tn.li); // issue 402
- }
- for(var i=0, l=ac.length; i<l; i++) {
- if( ac[i] === tn ) {
- this.childList.splice(i, 1);
-// delete tn; // JSLint complained
- break;
- }
- }
- },
-
- removeChildren: function(isRecursiveCall, retainPersistence) {
- // Remove all child nodes (more efficiently than recursive remove())
- this.tree.logDebug("%s.removeChildren(%o)", this, isRecursiveCall);
- var tree = this.tree;
- var ac = this.childList;
- if( ac ) {
- for(var i=0, l=ac.length; i<l; i++) {
- var tn = ac[i];
- if ( tn === tree.activeNode && !retainPersistence ){
- tn.deactivate();
- }
- if( this.tree.options.persist && !retainPersistence ) {
- if( tn.bSelected ){
- this.tree.persistence.clearSelect(tn.data.key);
- }
- if ( tn.bExpanded ){
- this.tree.persistence.clearExpand(tn.data.key);
- }
- }
- tn.removeChildren(true, retainPersistence);
- if(this.ul){
-// this.ul.removeChild(tn.li);
- $("li", $(this.ul)).remove(); // issue 231
- }
-// delete tn; JSLint complained
- }
- // Set to 'null' which is interpreted as 'not yet loaded' for lazy
- // nodes
- this.childList = null;
- }
- if( ! isRecursiveCall ) {
-// this._expand(false);
-// this.isRead = false;
- this._isLoading = false;
- this.render();
- }
- },
-
- setTitle: function(title) {
- this.fromDict({title: title});
- },
-
- reload: function(force) {
- throw "Use reloadChildren() instead";
- },
-
- reloadChildren: function(callback) {
- // Reload lazy content (expansion state is maintained).
- if( this.parent === null ){
- throw "Use tree.reload() instead";
- }else if( ! this.data.isLazy ){
- throw "node.reloadChildren() requires lazy nodes.";
- }
- // appendAjax triggers 'nodeLoaded' event.
- // We listen to this, if a callback was passed to reloadChildren
- if(callback){
- var self = this;
- var eventType = "nodeLoaded.dynatree." + this.tree.$tree.attr("id") + "." + this.data.key;
- this.tree.$tree.bind(eventType, function(e, node, isOk){
- self.tree.$tree.unbind(eventType);
- self.tree.logDebug("loaded %o, %o, %o", e, node, isOk);
- if(node !== self){
- throw "got invalid load event";
- }
- callback.call(self.tree, node, isOk);
- });
- }
- // The expansion state is maintained
- this.removeChildren();
- this._loadContent();
-// if( this.bExpanded ) {
-// // Remove children first, to prevent effects being applied
-// this.removeChildren();
-// // then force re-expand to trigger lazy loading
-//// this.expand(false);
-//// this.expand(true);
-// this._loadContent();
-// } else {
-// this.removeChildren();
-// this._loadContent();
-// }
- },
-
- /**
- * Make sure the node with a given key path is available in the tree.
- */
- _loadKeyPath: function(keyPath, callback) {
- var tree = this.tree;
- tree.logDebug("%s._loadKeyPath(%s)", this, keyPath);
- if(keyPath === ""){
- throw "Key path must not be empty";
- }
- var segList = keyPath.split(tree.options.keyPathSeparator);
- if(segList[0] === ""){
- throw "Key path must be relative (don't start with '/')";
- }
- var seg = segList.shift();
- if(this.childList){
- for(var i=0, l=this.childList.length; i < l; i++){
- var child = this.childList[i];
- if( child.data.key === seg ){
- if(segList.length === 0) {
- // Found the end node
- callback.call(tree, child, "ok");
-
- }else if(child.data.isLazy && (child.childList === null || child.childList === undefined)){
- tree.logDebug("%s._loadKeyPath(%s) -> reloading %s...", this, keyPath, child);
- var self = this;
- // Note: this line gives a JSLint warning (Don't make functions within a loop)
- /*jshint loopfunc:true */
- child.reloadChildren(function(node, isOk){
- // After loading, look for direct child with that key
- if(isOk){
- tree.logDebug("%s._loadKeyPath(%s) -> reloaded %s.", node, keyPath, node);
- callback.call(tree, child, "loaded");
- node._loadKeyPath(segList.join(tree.options.keyPathSeparator), callback);
- }else{
- tree.logWarning("%s._loadKeyPath(%s) -> reloadChildren() failed.", self, keyPath);
- callback.call(tree, child, "error");
- }
- });
- // we can ignore it, since it will only be exectuted once, the the loop is ended
- // See also http://stackoverflow.com/questions/3037598/how-to-get-around-the-jslint-error-dont-make-functions-within-a-loop
- } else {
- callback.call(tree, child, "loaded");
- // Look for direct child with that key
- child._loadKeyPath(segList.join(tree.options.keyPathSeparator), callback);
- }
- return;
- }
- }
- }
- // Could not find key
- // Callback params: child: undefined, the segment, isEndNode (segList.length === 0)
- callback.call(tree, undefined, "notfound", seg, segList.length === 0);
- tree.logWarning("Node not found: " + seg);
- return;
- },
-
- resetLazy: function() {
- // Discard lazy content.
- if( this.parent === null ){
- throw "Use tree.reload() instead";
- }else if( ! this.data.isLazy ){
- throw "node.resetLazy() requires lazy nodes.";
- }
- this.expand(false);
- this.removeChildren();
- },
-
- _addChildNode: function(dtnode, beforeNode) {
- /**
- * Internal function to add one single DynatreeNode as a child.
- *
- */
- var tree = this.tree,
- opts = tree.options,
- pers = tree.persistence;
-
-// tree.logDebug("%s._addChildNode(%o)", this, dtnode);
-
- // --- Update and fix dtnode attributes if necessary
- dtnode.parent = this;
-// if( beforeNode && (beforeNode.parent !== this || beforeNode === dtnode ) )
-// throw "<beforeNode> must be another child of <this>";
-
- // --- Add dtnode as a child
- if ( this.childList === null ) {
- this.childList = [];
- } else if( ! beforeNode ) {
- // Fix 'lastsib'
- if(this.childList.length > 0) {
- $(this.childList[this.childList.length-1].span).removeClass(opts.classNames.lastsib);
- }
- }
- if( beforeNode ) {
- var iBefore = $.inArray(beforeNode, this.childList);
- if( iBefore < 0 ){
- throw "<beforeNode> must be a child of <this>";
- }
- this.childList.splice(iBefore, 0, dtnode);
- } else {
- // Append node
- this.childList.push(dtnode);
- }
-
- // --- Handle persistence
- // Initial status is read from cookies, if persistence is active and
- // cookies are already present.
- // Otherwise the status is read from the data attributes and then persisted.
- var isInitializing = tree.isInitializing();
- if( opts.persist && pers.cookiesFound && isInitializing ) {
- // Init status from cookies
-// tree.logDebug("init from cookie, pa=%o, dk=%o", pers.activeKey, dtnode.data.key);
- if( pers.activeKey === dtnode.data.key ){
- tree.activeNode = dtnode;
- }
- if( pers.focusedKey === dtnode.data.key ){
- tree.focusNode = dtnode;
- }
- dtnode.bExpanded = ($.inArray(dtnode.data.key, pers.expandedKeyList) >= 0);
- dtnode.bSelected = ($.inArray(dtnode.data.key, pers.selectedKeyList) >= 0);
-// tree.logDebug(" key=%o, bSelected=%o", dtnode.data.key, dtnode.bSelected);
- } else {
- // Init status from data (Note: we write the cookies after the init phase)
-// tree.logDebug("init from data");
- if( dtnode.data.activate ) {
- tree.activeNode = dtnode;
- if( opts.persist ){
- pers.activeKey = dtnode.data.key;
- }
- }
- if( dtnode.data.focus ) {
- tree.focusNode = dtnode;
- if( opts.persist ){
- pers.focusedKey = dtnode.data.key;
- }
- }
- dtnode.bExpanded = ( dtnode.data.expand === true ); // Collapsed by default
- if( dtnode.bExpanded && opts.persist ){
- pers.addExpand(dtnode.data.key);
- }
- dtnode.bSelected = ( dtnode.data.select === true ); // Deselected by default
-/*
- Doesn't work, cause pers.selectedKeyList may be null
- if( dtnode.bSelected && opts.selectMode==1
- && pers.selectedKeyList && pers.selectedKeyList.length>0 ) {
- tree.logWarning("Ignored multi-selection in single-mode for %o", dtnode);
- dtnode.bSelected = false; // Fixing bad input data (multi selection for mode:1)
- }
-*/
- if( dtnode.bSelected && opts.persist ){
- pers.addSelect(dtnode.data.key);
- }
- }
-
- // Always expand, if it's below minExpandLevel
-// tree.logDebug ("%s._addChildNode(%o), l=%o", this, dtnode, dtnode.getLevel());
- if ( opts.minExpandLevel >= dtnode.getLevel() ) {
-// tree.logDebug ("Force expand for %o", dtnode);
- this.bExpanded = true;
- }
-
- // In multi-hier mode, update the parents selection state
- // issue #82: only if not initializing, because the children may not exist yet
-// if( !dtnode.data.isStatusNode && opts.selectMode==3 && !isInitializing )
-// dtnode._fixSelectionState();
-
- // In multi-hier mode, update the parents selection state
- if( dtnode.bSelected && opts.selectMode==3 ) {
- var p = this;
- while( p ) {
- if( !p.hasSubSel ){
- p._setSubSel(true);
- }
- p = p.parent;
- }
- }
- // render this node and the new child
- if ( tree.bEnableUpdate ){
- this.render();
- }
- return dtnode;
- },
-
- addChild: function(obj, beforeNode) {
- /**
- * Add a node object as child.
- *
- * This should be the only place, where a DynaTreeNode is constructed!
- * (Except for the root node creation in the tree constructor)
- *
- * @param obj A JS object (may be recursive) or an array of those.
- * @param {DynaTreeNode} beforeNode (optional) sibling node.
- *
- * Data format: array of node objects, with optional 'children' attributes.
- * [
- * { title: "t1", isFolder: true, ... }
- * { title: "t2", isFolder: true, ...,
- * children: [
- * {title: "t2.1", ..},
- * {..}
- * ]
- * }
- * ]
- * A simple object is also accepted instead of an array.
- *
- */
-// this.tree.logDebug("%s.addChild(%o, %o)", this, obj, beforeNode);
- if(typeof(obj) == "string"){
- throw "Invalid data type for " + obj;
- }else if( !obj || obj.length === 0 ){ // Passed null or undefined or empty array
- return;
- }else if( obj instanceof DynaTreeNode ){
- return this._addChildNode(obj, beforeNode);
- }
-
- if( !obj.length ){ // Passed a single data object
- obj = [ obj ];
- }
- var prevFlag = this.tree.enableUpdate(false);
-
- var tnFirst = null;
- for (var i=0, l=obj.length; i<l; i++) {
- var data = obj[i];
- var dtnode = this._addChildNode(new DynaTreeNode(this, this.tree, data), beforeNode);
- if( !tnFirst ){
- tnFirst = dtnode;
- }
- // Add child nodes recursively
- if( data.children ){
- dtnode.addChild(data.children, null);
- }
- }
- this.tree.enableUpdate(prevFlag);
- return tnFirst;
- },
-
- append: function(obj) {
- this.tree.logWarning("node.append() is deprecated (use node.addChild() instead).");
- return this.addChild(obj, null);
- },
-
- appendAjax: function(ajaxOptions) {
- var self = this;
- this.removeChildren(false, true);
- this.setLazyNodeStatus(DTNodeStatus_Loading);
- // Debug feature: force a delay, to simulate slow loading...
- if(ajaxOptions.debugLazyDelay){
- var ms = ajaxOptions.debugLazyDelay;
- ajaxOptions.debugLazyDelay = 0;
- this.tree.logInfo("appendAjax: waiting for debugLazyDelay " + ms);
- setTimeout(function(){self.appendAjax(ajaxOptions);}, ms);
- return;
- }
- // Ajax option inheritance: $.ajaxSetup < $.ui.dynatree.prototype.options.ajaxDefaults < tree.options.ajaxDefaults < ajaxOptions
- var orgSuccess = ajaxOptions.success,
- orgError = ajaxOptions.error,
- eventType = "nodeLoaded.dynatree." + this.tree.$tree.attr("id") + "." + this.data.key;
- var options = $.extend({}, this.tree.options.ajaxDefaults, ajaxOptions, {
- success: function(data, textStatus, jqXHR){
- // <this> is the request options
-// self.tree.logDebug("appendAjax().success");
- var prevPhase = self.tree.phase;
- self.tree.phase = "init";
- // postProcess is similar to the standard dataFilter hook,
- // but it is also called for JSONP
- if( options.postProcess ){
- data = options.postProcess.call(this, data, this.dataType);
- }
- // Process ASPX WebMethod JSON object inside "d" property
- // http://code.google.com/p/dynatree/issues/detail?id=202
- else if (data && data.hasOwnProperty("d")) {
- data = (typeof data.d) == "string" ? $.parseJSON(data.d) : data.d;
- }
- if(!$.isArray(data) || data.length !== 0){
- self.addChild(data, null);
- }
- self.tree.phase = "postInit";
- if( orgSuccess ){
- orgSuccess.call(options, self, data, textStatus);
- }
- self.tree.logDebug("trigger " + eventType);
- self.tree.$tree.trigger(eventType, [self, true]);
- self.tree.phase = prevPhase;
- // This should be the last command, so node._isLoading is true
- // while the callbacks run
- self.setLazyNodeStatus(DTNodeStatus_Ok);
- if($.isArray(data) && data.length === 0){
- // Set to [] which is interpreted as 'no children' for lazy
- // nodes
- self.childList = [];
- self.render();
- }
- },
- error: function(jqXHR, textStatus, errorThrown){
- // <this> is the request options
- self.tree.logWarning("appendAjax failed:", textStatus, ":\n", jqXHR, "\n", errorThrown);
- if( orgError ){
- orgError.call(options, self, jqXHR, textStatus, errorThrown);
- }
- self.tree.$tree.trigger(eventType, [self, false]);
- self.setLazyNodeStatus(DTNodeStatus_Error, {info: textStatus, tooltip: "" + errorThrown});
- }
- });
- $.ajax(options);
- },
-
- move: function(targetNode, mode) {
- /**Move this node to targetNode.
- * mode 'child': append this node as last child of targetNode.
- * This is the default. To be compatble with the D'n'd
- * hitMode, we also accept 'over'.
- * mode 'before': add this node as sibling before targetNode.
- * mode 'after': add this node as sibling after targetNode.
- */
- var pos;
- if(this === targetNode){
- return;
- }
- if( !this.parent ){
- throw "Cannot move system root";
- }
- if(mode === undefined || mode == "over"){
- mode = "child";
- }
- var prevParent = this.parent;
- var targetParent = (mode === "child") ? targetNode : targetNode.parent;
- if( targetParent.isDescendantOf(this) ){
- throw "Cannot move a node to it's own descendant";
- }
- // Unlink this node from current parent
- if( this.parent.childList.length == 1 ) {
- this.parent.childList = this.parent.data.isLazy ? [] : null;
- this.parent.bExpanded = false;
- } else {
- pos = $.inArray(this, this.parent.childList);
- if( pos < 0 ){
- throw "Internal error";
- }
- this.parent.childList.splice(pos, 1);
- }
- // Remove from source DOM parent
- if(this.parent.ul){
- this.parent.ul.removeChild(this.li);
- }
-
- // Insert this node to target parent's child list
- this.parent = targetParent;
- if( targetParent.hasChildren() ) {
- switch(mode) {
- case "child":
- // Append to existing target children
- targetParent.childList.push(this);
- break;
- case "before":
- // Insert this node before target node
- pos = $.inArray(targetNode, targetParent.childList);
- if( pos < 0 ){
- throw "Internal error";
- }
- targetParent.childList.splice(pos, 0, this);
- break;
- case "after":
- // Insert this node after target node
- pos = $.inArray(targetNode, targetParent.childList);
- if( pos < 0 ){
- throw "Internal error";
- }
- targetParent.childList.splice(pos+1, 0, this);
- break;
- default:
- throw "Invalid mode " + mode;
- }
- } else {
- targetParent.childList = [ this ];
- }
- // Parent has no <ul> tag yet:
- if( !targetParent.ul ) {
- // This is the parent's first child: create UL tag
- // (Hidden, because it will be
- targetParent.ul = document.createElement("ul");
- targetParent.ul.style.display = "none";
- targetParent.li.appendChild(targetParent.ul);
- }
- // Issue 319: Add to target DOM parent (only if node was already rendered(expanded))
- if(this.li){
- targetParent.ul.appendChild(this.li);
- }
-
- if( this.tree !== targetNode.tree ) {
- // Fix node.tree for all source nodes
- this.visit(function(node){
- node.tree = targetNode.tree;
- }, null, true);
- throw "Not yet implemented.";
- }
- // TODO: fix selection state
- // TODO: fix active state
- if( !prevParent.isDescendantOf(targetParent)) {
- prevParent.render();
- }
- if( !targetParent.isDescendantOf(prevParent) ) {
- targetParent.render();
- }
-// this.tree.redraw();
-/*
- var tree = this.tree;
- var opts = tree.options;
- var pers = tree.persistence;
-
-
- // Always expand, if it's below minExpandLevel
-// tree.logDebug ("%s._addChildNode(%o), l=%o", this, dtnode, dtnode.getLevel());
- if ( opts.minExpandLevel >= dtnode.getLevel() ) {
-// tree.logDebug ("Force expand for %o", dtnode);
- this.bExpanded = true;
- }
-
- // In multi-hier mode, update the parents selection state
- // issue #82: only if not initializing, because the children may not exist yet
-// if( !dtnode.data.isStatusNode && opts.selectMode==3 && !isInitializing )
-// dtnode._fixSelectionState();
-
- // In multi-hier mode, update the parents selection state
- if( dtnode.bSelected && opts.selectMode==3 ) {
- var p = this;
- while( p ) {
- if( !p.hasSubSel )
- p._setSubSel(true);
- p = p.parent;
- }
- }
- // render this node and the new child
- if ( tree.bEnableUpdate )
- this.render();
-
- return dtnode;
-
-*/
- },
-
- // --- end of class
- lastentry: undefined
-};
-
-/*************************************************************************
- * class DynaTreeStatus
- */
-
-var DynaTreeStatus = Class.create();
-
-
-DynaTreeStatus._getTreePersistData = function(cookieId, cookieOpts) {
- // Static member: Return persistence information from cookies
- var ts = new DynaTreeStatus(cookieId, cookieOpts);
- ts.read();
- return ts.toDict();
-};
-// Make available in global scope
-getDynaTreePersistData = DynaTreeStatus._getTreePersistData; // TODO: deprecated
-
-
-DynaTreeStatus.prototype = {
- // Constructor
- initialize: function(cookieId, cookieOpts) {
-// this._log("DynaTreeStatus: initialize");
- if( cookieId === undefined ){
- cookieId = $.ui.dynatree.prototype.options.cookieId;
- }
- cookieOpts = $.extend({}, $.ui.dynatree.prototype.options.cookie, cookieOpts);
-
- this.cookieId = cookieId;
- this.cookieOpts = cookieOpts;
- this.cookiesFound = undefined;
- this.activeKey = null;
- this.focusedKey = null;
- this.expandedKeyList = null;
- this.selectedKeyList = null;
- },
- // member functions
- _log: function(msg) {
- // this.logDebug("_changeNodeList(%o): nodeList:%o, idx:%o", mode, nodeList, idx);
- Array.prototype.unshift.apply(arguments, ["debug"]);
- _log.apply(this, arguments);
- },
- read: function() {
-// this._log("DynaTreeStatus: read");
- // Read or init cookies.
- this.cookiesFound = false;
-
- var cookie = $.cookie(this.cookieId + "-active");
- this.activeKey = ( cookie === null ) ? "" : cookie;
- if( cookie !== null ){
- this.cookiesFound = true;
- }
- cookie = $.cookie(this.cookieId + "-focus");
- this.focusedKey = ( cookie === null ) ? "" : cookie;
- if( cookie !== null ){
- this.cookiesFound = true;
- }
- cookie = $.cookie(this.cookieId + "-expand");
- this.expandedKeyList = ( cookie === null ) ? [] : cookie.split(",");
- if( cookie !== null ){
- this.cookiesFound = true;
- }
- cookie = $.cookie(this.cookieId + "-select");
- this.selectedKeyList = ( cookie === null ) ? [] : cookie.split(",");
- if( cookie !== null ){
- this.cookiesFound = true;
- }
- },
- write: function() {
-// this._log("DynaTreeStatus: write");
- $.cookie(this.cookieId + "-active", ( this.activeKey === null ) ? "" : this.activeKey, this.cookieOpts);
- $.cookie(this.cookieId + "-focus", ( this.focusedKey === null ) ? "" : this.focusedKey, this.cookieOpts);
- $.cookie(this.cookieId + "-expand", ( this.expandedKeyList === null ) ? "" : this.expandedKeyList.join(","), this.cookieOpts);
- $.cookie(this.cookieId + "-select", ( this.selectedKeyList === null ) ? "" : this.selectedKeyList.join(","), this.cookieOpts);
- },
- addExpand: function(key) {
-// this._log("addExpand(%o)", key);
- if( $.inArray(key, this.expandedKeyList) < 0 ) {
- this.expandedKeyList.push(key);
- $.cookie(this.cookieId + "-expand", this.expandedKeyList.join(","), this.cookieOpts);
- }
- },
- clearExpand: function(key) {
-// this._log("clearExpand(%o)", key);
- var idx = $.inArray(key, this.expandedKeyList);
- if( idx >= 0 ) {
- this.expandedKeyList.splice(idx, 1);
- $.cookie(this.cookieId + "-expand", this.expandedKeyList.join(","), this.cookieOpts);
- }
- },
- addSelect: function(key) {
-// this._log("addSelect(%o)", key);
- if( $.inArray(key, this.selectedKeyList) < 0 ) {
- this.selectedKeyList.push(key);
- $.cookie(this.cookieId + "-select", this.selectedKeyList.join(","), this.cookieOpts);
- }
- },
- clearSelect: function(key) {
-// this._log("clearSelect(%o)", key);
- var idx = $.inArray(key, this.selectedKeyList);
- if( idx >= 0 ) {
- this.selectedKeyList.splice(idx, 1);
- $.cookie(this.cookieId + "-select", this.selectedKeyList.join(","), this.cookieOpts);
- }
- },
- isReloading: function() {
- return this.cookiesFound === true;
- },
- toDict: function() {
- return {
- cookiesFound: this.cookiesFound,
- activeKey: this.activeKey,
- focusedKey: this.activeKey,
- expandedKeyList: this.expandedKeyList,
- selectedKeyList: this.selectedKeyList
- };
- },
- // --- end of class
- lastentry: undefined
-};
-
-
-/*************************************************************************
- * class DynaTree
- */
-
-var DynaTree = Class.create();
-
-// --- Static members ----------------------------------------------------------
-
-DynaTree.version = "$Version: 1.2.4$";
-
-/*
-DynaTree._initTree = function() {
-};
-
-DynaTree._bind = function() {
-};
-*/
-//--- Class members ------------------------------------------------------------
-
-DynaTree.prototype = {
- // Constructor
-// initialize: function(divContainer, options) {
- initialize: function($widget) {
- // instance members
- this.phase = "init";
- this.$widget = $widget;
- this.options = $widget.options;
- this.$tree = $widget.element;
- this.timer = null;
- // find container element
- this.divTree = this.$tree.get(0);
-
-// var parentPos = $(this.divTree).parent().offset();
-// this.parentTop = parentPos.top;
-// this.parentLeft = parentPos.left;
-
- _initDragAndDrop(this);
- },
-
- // member functions
-
- _load: function(callback) {
- var $widget = this.$widget;
- var opts = this.options,
- self = this;
- this.bEnableUpdate = true;
- this._nodeCount = 1;
- this.activeNode = null;
- this.focusNode = null;
-
- // Some deprecation warnings to help with migration
- if( opts.rootVisible !== undefined ){
- this.logWarning("Option 'rootVisible' is no longer supported.");
- }
- if( opts.minExpandLevel < 1 ) {
- this.logWarning("Option 'minExpandLevel' must be >= 1.");
- opts.minExpandLevel = 1;
- }
-// _log("warn", "jQuery.support.boxModel " + jQuery.support.boxModel);
-
- // If a 'options.classNames' dictionary was passed, still use defaults
- // for undefined classes:
- if( opts.classNames !== $.ui.dynatree.prototype.options.classNames ) {
- opts.classNames = $.extend({}, $.ui.dynatree.prototype.options.classNames, opts.classNames);
- }
- if( opts.ajaxDefaults !== $.ui.dynatree.prototype.options.ajaxDefaults ) {
- opts.ajaxDefaults = $.extend({}, $.ui.dynatree.prototype.options.ajaxDefaults, opts.ajaxDefaults);
- }
- if( opts.dnd !== $.ui.dynatree.prototype.options.dnd ) {
- opts.dnd = $.extend({}, $.ui.dynatree.prototype.options.dnd, opts.dnd);
- }
- // Guess skin path, if not specified
- if(!opts.imagePath) {
- $("script").each( function () {
- var _rexDtLibName = /.*dynatree[^\/]*\.js$/i;
- if( this.src.search(_rexDtLibName) >= 0 ) {
- if( this.src.indexOf("/")>=0 ){ // issue #47
- opts.imagePath = this.src.slice(0, this.src.lastIndexOf("/")) + "/skin/";
- }else{
- opts.imagePath = "skin/";
- }
- self.logDebug("Guessing imagePath from '%s': '%s'", this.src, opts.imagePath);
- return false; // first match
- }
- });
- }
-
- this.persistence = new DynaTreeStatus(opts.cookieId, opts.cookie);
- if( opts.persist ) {
- if( !$.cookie ){
- _log("warn", "Please include jquery.cookie.js to use persistence.");
- }
- this.persistence.read();
- }
- this.logDebug("DynaTree.persistence: %o", this.persistence.toDict());
-
- // Cached tag strings
- this.cache = {
- tagEmpty: "<span class='" + opts.classNames.empty + "'></span>",
- tagVline: "<span class='" + opts.classNames.vline + "'></span>",
- tagExpander: "<span class='" + opts.classNames.expander + "'></span>",
- tagConnector: "<span class='" + opts.classNames.connector + "'></span>",
- tagNodeIcon: "<span class='" + opts.classNames.nodeIcon + "'></span>",
- tagCheckbox: "<span class='" + opts.classNames.checkbox + "'></span>",
- lastentry: undefined
- };
-
- // Clear container, in case it contained some 'waiting' or 'error' text
- // for clients that don't support JS.
- // We don't do this however, if we try to load from an embedded UL element.
- if( opts.children || (opts.initAjax && opts.initAjax.url) || opts.initId ){
- $(this.divTree).empty();
- }
- var $ulInitialize = this.$tree.find(">ul:first").hide();
-
- // Create the root element
- this.tnRoot = new DynaTreeNode(null, this, {});
- this.tnRoot.bExpanded = true;
- this.tnRoot.render();
- this.divTree.appendChild(this.tnRoot.ul);
-
- var root = this.tnRoot,
- isReloading = ( opts.persist && this.persistence.isReloading() ),
- isLazy = false,
- prevFlag = this.enableUpdate(false);
-
- this.logDebug("Dynatree._load(): read tree structure...");
-
- // Init tree structure
- if( opts.children ) {
- // Read structure from node array
- root.addChild(opts.children);
-
- } else if( opts.initAjax && opts.initAjax.url ) {
- // Init tree from AJAX request
- isLazy = true;
- root.data.isLazy = true;
- this._reloadAjax(callback);
-
- } else if( opts.initId ) {
- // Init tree from another UL element
- this._createFromTag(root, $("#"+opts.initId));
-
- } else {
- // Init tree from the first UL element inside the container <div>
-// var $ul = this.$tree.find(">ul:first").hide();
- this._createFromTag(root, $ulInitialize);
- $ulInitialize.remove();
- }
-
- this._checkConsistency();
- // Fix part-sel flags
- if(!isLazy && opts.selectMode == 3){
- root._updatePartSelectionState();
- }
- // Render html markup
- this.logDebug("Dynatree._load(): render nodes...");
- this.enableUpdate(prevFlag);
-
- // bind event handlers
- this.logDebug("Dynatree._load(): bind events...");
- this.$widget.bind();
-
- // --- Post-load processing
- this.logDebug("Dynatree._load(): postInit...");
- this.phase = "postInit";
-
- // In persist mode, make sure that cookies are written, even if they are empty
- if( opts.persist ) {
- this.persistence.write();
- }
- // Set focus, if possible (this will also fire an event and write a cookie)
- if( this.focusNode && this.focusNode.isVisible() ) {
- this.logDebug("Focus on init: %o", this.focusNode);
- this.focusNode.focus();
- }
- if( !isLazy ) {
- if( opts.onPostInit ) {
- opts.onPostInit.call(this, isReloading, false);
- }
- if( callback ){
- callback.call(this, "ok");
- }
- }
- this.phase = "idle";
- },
-
- _reloadAjax: function(callback) {
- // Reload
- var opts = this.options;
- if( ! opts.initAjax || ! opts.initAjax.url ){
- throw "tree.reload() requires 'initAjax' mode.";
- }
- var pers = this.persistence;
- var ajaxOpts = $.extend({}, opts.initAjax);
- // Append cookie info to the request
-// this.logDebug("reloadAjax: key=%o, an.key:%o", pers.activeKey, this.activeNode?this.activeNode.data.key:"?");
- if( ajaxOpts.addActiveKey ){
- ajaxOpts.data.activeKey = pers.activeKey;
- }
- if( ajaxOpts.addFocusedKey ){
- ajaxOpts.data.focusedKey = pers.focusedKey;
- }
- if( ajaxOpts.addExpandedKeyList ){
- ajaxOpts.data.expandedKeyList = pers.expandedKeyList.join(",");
- }
- if( ajaxOpts.addSelectedKeyList ){
- ajaxOpts.data.selectedKeyList = pers.selectedKeyList.join(",");
- }
- // Set up onPostInit callback to be called when Ajax returns
- if( ajaxOpts.success ){
- this.logWarning("initAjax: success callback is ignored; use onPostInit instead.");
- }
- if( ajaxOpts.error ){
- this.logWarning("initAjax: error callback is ignored; use onPostInit instead.");
- }
- var isReloading = pers.isReloading();
- ajaxOpts.success = function(dtnode, data, textStatus) {
- if(opts.selectMode == 3){
- dtnode.tree.tnRoot._updatePartSelectionState();
- }
- if(opts.onPostInit){
- opts.onPostInit.call(dtnode.tree, isReloading, false);
- }
- if(callback){
- callback.call(dtnode.tree, "ok");
- }
- };
- ajaxOpts.error = function(dtnode, XMLHttpRequest, textStatus, errorThrown) {
- if(opts.onPostInit){
- opts.onPostInit.call(dtnode.tree, isReloading, true, XMLHttpRequest, textStatus, errorThrown);
- }
- if(callback){
- callback.call(dtnode.tree, "error", XMLHttpRequest, textStatus, errorThrown);
- }
- };
-// }
- this.logDebug("Dynatree._init(): send Ajax request...");
- this.tnRoot.appendAjax(ajaxOpts);
- },
-
- toString: function() {
-// return "DynaTree '" + this.options.title + "'";
- return "Dynatree '" + this.$tree.attr("id") + "'";
- },
-
- toDict: function() {
- return this.tnRoot.toDict(true);
- },
-
- serializeArray: function(stopOnParents) {
- // Return a JavaScript array of objects, ready to be encoded as a JSON
- // string for selected nodes
- var nodeList = this.getSelectedNodes(stopOnParents),
- name = this.$tree.attr("name") || this.$tree.attr("id"),
- arr = [];
- for(var i=0, l=nodeList.length; i<l; i++){
- arr.push({name: name, value: nodeList[i].data.key});
- }
- return arr;
- },
-
- getPersistData: function() {
- return this.persistence.toDict();
- },
-
- logDebug: function(msg) {
- if( this.options.debugLevel >= 2 ) {
- Array.prototype.unshift.apply(arguments, ["debug"]);
- _log.apply(this, arguments);
- }
- },
-
- logInfo: function(msg) {
- if( this.options.debugLevel >= 1 ) {
- Array.prototype.unshift.apply(arguments, ["info"]);
- _log.apply(this, arguments);
- }
- },
-
- logWarning: function(msg) {
- Array.prototype.unshift.apply(arguments, ["warn"]);
- _log.apply(this, arguments);
- },
-
- isInitializing: function() {
- return ( this.phase=="init" || this.phase=="postInit" );
- },
- isReloading: function() {
- return ( this.phase=="init" || this.phase=="postInit" ) && this.options.persist && this.persistence.cookiesFound;
- },
- isUserEvent: function() {
- return ( this.phase=="userEvent" );
- },
-
- redraw: function() {
-// this.logDebug("dynatree.redraw()...");
- this.tnRoot.render(false, false);
-// this.logDebug("dynatree.redraw() done.");
- },
- renderInvisibleNodes: function() {
- this.tnRoot.render(false, true);
- },
- reload: function(callback) {
- this._load(callback);
- },
-
- getRoot: function() {
- return this.tnRoot;
- },
-
- enable: function() {
- this.$widget.enable();
- },
-
- disable: function() {
- this.$widget.disable();
- },
-
- getNodeByKey: function(key) {
- // Search the DOM by element ID (assuming this is faster than traversing all nodes).
- // $("#...") has problems, if the key contains '.', so we use getElementById()
- var el = document.getElementById(this.options.idPrefix + key);
- if( el ){
- return el.dtnode ? el.dtnode : null;
- }
- // Not found in the DOM, but still may be in an unrendered part of tree
- var match = null;
- this.visit(function(node){
-// window.console.log("%s", node);
- if(node.data.key === key) {
- match = node;
- return false;
- }
- }, true);
- return match;
- },
-
- getActiveNode: function() {
- return this.activeNode;
- },
-
- reactivate: function(setFocus) {
- // Re-fire onQueryActivate and onActivate events.
- var node = this.activeNode;
-// this.logDebug("reactivate %o", node);
- if( node ) {
- this.activeNode = null; // Force re-activating
- node.activate();
- if( setFocus ){
- node.focus();
- }
- }
- },
-
- getSelectedNodes: function(stopOnParents) {
- var nodeList = [];
- this.tnRoot.visit(function(node){
- if( node.bSelected ) {
- nodeList.push(node);
- if( stopOnParents === true ){
- return "skip"; // stop processing this branch
- }
- }
- });
- return nodeList;
- },
-
- activateKey: function(key) {
- var dtnode = (key === null) ? null : this.getNodeByKey(key);
- if( !dtnode ) {
- if( this.activeNode ){
- this.activeNode.deactivate();
- }
- this.activeNode = null;
- return null;
- }
- dtnode.focus();
- dtnode.activate();
- return dtnode;
- },
-
- loadKeyPath: function(keyPath, callback) {
- var segList = keyPath.split(this.options.keyPathSeparator);
- // Remove leading '/'
- if(segList[0] === ""){
- segList.shift();
- }
- // Remove leading system root key
- if(segList[0] == this.tnRoot.data.key){
- this.logDebug("Removed leading root key.");
- segList.shift();
- }
- keyPath = segList.join(this.options.keyPathSeparator);
- return this.tnRoot._loadKeyPath(keyPath, callback);
- },
-
- selectKey: function(key, select) {
- var dtnode = this.getNodeByKey(key);
- if( !dtnode ){
- return null;
- }
- dtnode.select(select);
- return dtnode;
- },
-
- enableUpdate: function(bEnable) {
- if ( this.bEnableUpdate==bEnable ){
- return bEnable;
- }
- this.bEnableUpdate = bEnable;
- if ( bEnable ){
- this.redraw();
- }
- return !bEnable; // return previous value
- },
-
- count: function() {
- return this.tnRoot.countChildren();
- },
-
- visit: function(fn, includeRoot) {
- return this.tnRoot.visit(fn, includeRoot);
- },
-
- _createFromTag: function(parentTreeNode, $ulParent) {
- // Convert a <UL>...</UL> list into children of the parent tree node.
- var self = this;
-/*
-TODO: better?
- this.$lis = $("li:has(a[href])", this.element);
- this.$tabs = this.$lis.map(function() { return $("a", this)[0]; });
- */
- $ulParent.find(">li").each(function() {
- var $li = $(this),
- $liSpan = $li.find(">span:first"),
- $liA = $li.find(">a:first"),
- title,
- href = null,
- target = null,
- tooltip;
- if( $liSpan.length ) {
- // If a <li><span> tag is specified, use it literally.
- title = $liSpan.html();
- } else if( $liA.length ) {
- title = $liA.html();
- href = $liA.attr("href");
- target = $liA.attr("target");
- tooltip = $liA.attr("title");
- } else {
- // If only a <li> tag is specified, use the trimmed string up to
- // the next child <ul> tag.
- title = $li.html();
- var iPos = title.search(/<ul/i);
- if( iPos >= 0 ){
- title = $.trim(title.substring(0, iPos));
- }else{
- title = $.trim(title);
- }
-// self.logDebug("%o", title);
- }
- // Parse node options from ID, title and class attributes
- var data = {
- title: title,
- tooltip: tooltip,
- isFolder: $li.hasClass("folder"),
- isLazy: $li.hasClass("lazy"),
- expand: $li.hasClass("expanded"),
- select: $li.hasClass("selected"),
- activate: $li.hasClass("active"),
- focus: $li.hasClass("focused"),
- noLink: $li.hasClass("noLink")
- };
- if( href ){
- data.href = href;
- data.target = target;
- }
- if( $li.attr("title") ){
- data.tooltip = $li.attr("title"); // overrides <a title='...'>
- }
- if( $li.attr("id") ){
- data.key = "" + $li.attr("id");
- }
- // If a data attribute is present, evaluate as a JavaScript object
- if( $li.attr("data") ) {
- var dataAttr = $.trim($li.attr("data"));
- if( dataAttr ) {
- if( dataAttr.charAt(0) != "{" ){
- dataAttr = "{" + dataAttr + "}";
- }
- try {
- $.extend(data, eval("(" + dataAttr + ")"));
- } catch(e) {
- throw ("Error parsing node data: " + e + "\ndata:\n'" + dataAttr + "'");
- }
- }
- }
- var childNode = parentTreeNode.addChild(data);
- // Recursive reading of child nodes, if LI tag contains an UL tag
- var $ul = $li.find(">ul:first");
- if( $ul.length ) {
- self._createFromTag(childNode, $ul); // must use 'self', because 'this' is the each() context
- }
- });
- },
-
- _checkConsistency: function() {
-// this.logDebug("tree._checkConsistency() NOT IMPLEMENTED - %o", this);
- },
-
- _setDndStatus: function(sourceNode, targetNode, helper, hitMode, accept) {
- // hitMode: 'after', 'before', 'over', 'out', 'start', 'stop'
- var $source = sourceNode ? $(sourceNode.span) : null,
- $target = $(targetNode.span);
- if( !this.$dndMarker ) {
- this.$dndMarker = $("<div id='dynatree-drop-marker'></div>")
- .hide()
- .css({"z-index": 1000})
- .prependTo($(this.divTree).parent());
-
-// logMsg("Creating marker: %o", this.$dndMarker);
- }
-/*
- if(hitMode === "start"){
- }
- if(hitMode === "stop"){
-// sourceNode.removeClass("dynatree-drop-target");
- }
-*/
- if(hitMode === "after" || hitMode === "before" || hitMode === "over"){
-// $source && $source.addClass("dynatree-drag-source");
-// $target.addClass("dynatree-drop-target");
-
- var markerOffset = "0 0";
-
- switch(hitMode){
- case "before":
- this.$dndMarker.removeClass("dynatree-drop-after dynatree-drop-over");
- this.$dndMarker.addClass("dynatree-drop-before");
- markerOffset = "0 -8";
- break;
- case "after":
- this.$dndMarker.removeClass("dynatree-drop-before dynatree-drop-over");
- this.$dndMarker.addClass("dynatree-drop-after");
- markerOffset = "0 8";
- break;
- default:
- this.$dndMarker.removeClass("dynatree-drop-after dynatree-drop-before");
- this.$dndMarker.addClass("dynatree-drop-over");
- $target.addClass("dynatree-drop-target");
- markerOffset = "8 0";
- }
-// logMsg("Creating marker: %o", this.$dndMarker);
-// logMsg(" $target.offset=%o", $target);
-// logMsg(" pos/$target.offset=%o", pos);
-// logMsg(" $target.position=%o", $target.position());
-// logMsg(" $target.offsetParent=%o, ot:%o", $target.offsetParent(), $target.offsetParent().offset());
-// logMsg(" $(this.divTree).offset=%o", $(this.divTree).offset());
-// logMsg(" $(this.divTree).parent=%o", $(this.divTree).parent());
-// var pos = $target.offset();
-// var parentPos = $target.offsetParent().offset();
-// var bodyPos = $target.offsetParent().offset();
-
- this.$dndMarker
- .show()
- .position({
- my: "left top",
- at: "left top",
- of: $target,
- offset: markerOffset
- });
-
-// helper.addClass("dynatree-drop-hover");
- } else {
-// $source && $source.removeClass("dynatree-drag-source");
- $target.removeClass("dynatree-drop-target");
- this.$dndMarker.hide();
-// helper.removeClass("dynatree-drop-hover");
- }
- if(hitMode === "after"){
- $target.addClass("dynatree-drop-after");
- } else {
- $target.removeClass("dynatree-drop-after");
- }
- if(hitMode === "before"){
- $target.addClass("dynatree-drop-before");
- } else {
- $target.removeClass("dynatree-drop-before");
- }
- if(accept === true){
- if($source){
- $source.addClass("dynatree-drop-accept");
- }
- $target.addClass("dynatree-drop-accept");
- helper.addClass("dynatree-drop-accept");
- }else{
- if($source){
- $source.removeClass("dynatree-drop-accept");
- }
- $target.removeClass("dynatree-drop-accept");
- helper.removeClass("dynatree-drop-accept");
- }
- if(accept === false){
- if($source){
- $source.addClass("dynatree-drop-reject");
- }
- $target.addClass("dynatree-drop-reject");
- helper.addClass("dynatree-drop-reject");
- }else{
- if($source){
- $source.removeClass("dynatree-drop-reject");
- }
- $target.removeClass("dynatree-drop-reject");
- helper.removeClass("dynatree-drop-reject");
- }
- },
-
- _onDragEvent: function(eventName, node, otherNode, event, ui, draggable) {
- /**
- * Handles drag'n'drop functionality.
- *
- * A standard jQuery drag-and-drop process may generate these calls:
- *
- * draggable helper():
- * _onDragEvent("helper", sourceNode, null, event, null, null);
- * start:
- * _onDragEvent("start", sourceNode, null, event, ui, draggable);
- * drag:
- * _onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
- * _onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
- * _onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
- * stop:
- * _onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
- * _onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
- * _onDragEvent("stop", sourceNode, null, event, ui, draggable);
- */
-// if(eventName !== "over"){
-// this.logDebug("tree._onDragEvent(%s, %o, %o) - %o", eventName, node, otherNode, this);
-// }
- var opts = this.options,
- dnd = this.options.dnd,
- res = null,
- nodeTag = $(node.span),
- hitMode,
- enterResponse;
-
- switch (eventName) {
- case "helper":
- // Only event and node argument is available
- var $helper = $("<div class='dynatree-drag-helper'><span class='dynatree-drag-helper-img' /></div>")
- .append($(event.target).closest(".dynatree-title").clone());
-// .append($(event.target).closest('a').clone());
- // issue 244: helper should be child of scrollParent
- $("ul.dynatree-container", node.tree.divTree).append($helper);
-// $(node.tree.divTree).append($helper);
- // Attach node reference to helper object
- $helper.data("dtSourceNode", node);
-// this.logDebug("helper=%o", $helper);
-// this.logDebug("helper.sourceNode=%o", $helper.data("dtSourceNode"));
- res = $helper;
- break;
- case "start":
- if(node.isStatusNode()) {
- res = false;
- } else if(dnd.onDragStart) {
- res = dnd.onDragStart(node);
- }
- if(res === false) {
- this.logDebug("tree.onDragStart() cancelled");
- //draggable._clear();
- // NOTE: the return value seems to be ignored (drag is not canceled, when false is returned)
- ui.helper.trigger("mouseup");
- ui.helper.hide();
- } else {
- nodeTag.addClass("dynatree-drag-source");
- }
- break;
- case "enter":
- res = dnd.onDragEnter ? dnd.onDragEnter(node, otherNode) : null;
- if(!res){
- // convert null, undefined, false to false
- res = false;
- }else{
- res = {
- over: ((res === true) || (res === "over") || $.inArray("over", res) >= 0),
- before: ((res === true) || (res === "before") || $.inArray("before", res) >= 0),
- after: ((res === true) || (res === "after") || $.inArray("after", res) >= 0)
- };
- }
- ui.helper.data("enterResponse", res);
-// this.logDebug("helper.enterResponse: %o", res);
- break;
- case "over":
- enterResponse = ui.helper.data("enterResponse");
- hitMode = null;
- if(enterResponse === false){
- // Don't call onDragOver if onEnter returned false.
- // issue 332
-// break;
- } else if(typeof enterResponse === "string") {
- // Use hitMode from onEnter if provided.
- hitMode = enterResponse;
- } else {
- // Calculate hitMode from relative cursor position.
- var nodeOfs = nodeTag.offset();
-// var relPos = { x: event.clientX - nodeOfs.left,
-// y: event.clientY - nodeOfs.top };
-// nodeOfs.top += this.parentTop;
-// nodeOfs.left += this.parentLeft;
- var relPos = { x: event.pageX - nodeOfs.left,
- y: event.pageY - nodeOfs.top };
- var relPos2 = { x: relPos.x / nodeTag.width(),
- y: relPos.y / nodeTag.height() };
-// this.logDebug("event.page: %s/%s", event.pageX, event.pageY);
-// this.logDebug("event.client: %s/%s", event.clientX, event.clientY);
-// this.logDebug("nodeOfs: %s/%s", nodeOfs.left, nodeOfs.top);
-//// this.logDebug("parent: %s/%s", this.parentLeft, this.parentTop);
-// this.logDebug("relPos: %s/%s", relPos.x, relPos.y);
-// this.logDebug("relPos2: %s/%s", relPos2.x, relPos2.y);
- if( enterResponse.after && relPos2.y > 0.75 ){
- hitMode = "after";
- } else if(!enterResponse.over && enterResponse.after && relPos2.y > 0.5 ){
- hitMode = "after";
- } else if(enterResponse.before && relPos2.y <= 0.25) {
- hitMode = "before";
- } else if(!enterResponse.over && enterResponse.before && relPos2.y <= 0.5) {
- hitMode = "before";
- } else if(enterResponse.over) {
- hitMode = "over";
- }
- // Prevent no-ops like 'before source node'
- // TODO: these are no-ops when moving nodes, but not in copy mode
- if( dnd.preventVoidMoves ){
- if(node === otherNode){
-// this.logDebug(" drop over source node prevented");
- hitMode = null;
- }else if(hitMode === "before" && otherNode && node === otherNode.getNextSibling()){
-// this.logDebug(" drop after source node prevented");
- hitMode = null;
- }else if(hitMode === "after" && otherNode && node === otherNode.getPrevSibling()){
-// this.logDebug(" drop before source node prevented");
- hitMode = null;
- }else if(hitMode === "over" && otherNode && otherNode.parent === node && otherNode.isLastSibling() ){
-// this.logDebug(" drop last child over own parent prevented");
- hitMode = null;
- }
- }
-// this.logDebug("hitMode: %s - %s - %s", hitMode, (node.parent === otherNode), node.isLastSibling());
- ui.helper.data("hitMode", hitMode);
- }
- // Auto-expand node (only when 'over' the node, not 'before', or 'after')
- if(hitMode === "over" && dnd.autoExpandMS && node.hasChildren() !== false && !node.bExpanded) {
- node.scheduleAction("expand", dnd.autoExpandMS);
- }
- if(hitMode && dnd.onDragOver){
- res = dnd.onDragOver(node, otherNode, hitMode);
- if(res === "over" || res === "before" || res === "after") {
- hitMode = res;
- }
- }
- // issue 332
-// this._setDndStatus(otherNode, node, ui.helper, hitMode, res!==false);
- this._setDndStatus(otherNode, node, ui.helper, hitMode, res!==false && hitMode !== null);
- break;
- case "drop":
- // issue 286: don't trigger onDrop, if DnD status is 'reject'
- var isForbidden = ui.helper.hasClass("dynatree-drop-reject");
- hitMode = ui.helper.data("hitMode");
- if(hitMode && dnd.onDrop && !isForbidden){
- dnd.onDrop(node, otherNode, hitMode, ui, draggable);
- }
- break;
- case "leave":
- // Cancel pending expand request
- node.scheduleAction("cancel");
- ui.helper.data("enterResponse", null);
- ui.helper.data("hitMode", null);
- this._setDndStatus(otherNode, node, ui.helper, "out", undefined);
- if(dnd.onDragLeave){
- dnd.onDragLeave(node, otherNode);
- }
- break;
- case "stop":
- nodeTag.removeClass("dynatree-drag-source");
- if(dnd.onDragStop){
- dnd.onDragStop(node);
- }
- break;
- default:
- throw "Unsupported drag event: " + eventName;
- }
- return res;
- },
-
- cancelDrag: function() {
- var dd = $.ui.ddmanager.current;
- if(dd){
- dd.cancel();
- }
- },
-
- // --- end of class
- lastentry: undefined
-};
-
-/*************************************************************************
- * Widget $(..).dynatree
- */
-
-$.widget("ui.dynatree", {
-/*
- init: function() {
- // ui.core 1.6 renamed init() to _init(): this stub assures backward compatibility
- _log("warn", "ui.dynatree.init() was called; you should upgrade to jquery.ui.core.js v1.8 or higher.");
- return this._init();
- },
- */
- _init: function() {
-// if( parseFloat($.ui.version) < 1.8 ) {
- if(versionCompare($.ui.version, "1.8") < 0){
- // jquery.ui.core 1.8 renamed _init() to _create(): this stub assures backward compatibility
- if(this.options.debugLevel >= 0){
- _log("warn", "ui.dynatree._init() was called; you should upgrade to jquery.ui.core.js v1.8 or higher.");
- }
- return this._create();
- }
- // jquery.ui.core 1.8 still uses _init() to perform "default functionality"
- if(this.options.debugLevel >= 2){
- _log("debug", "ui.dynatree._init() was called; no current default functionality.");
- }
- },
-
- _create: function() {
- var opts = this.options;
- if(opts.debugLevel >= 1){
- logMsg("Dynatree._create(): version='%s', debugLevel=%o.", $.ui.dynatree.version, this.options.debugLevel);
- }
- // The widget framework supplies this.element and this.options.
- this.options.event += ".dynatree"; // namespace event
-
- var divTree = this.element.get(0);
-/* // Clear container, in case it contained some 'waiting' or 'error' text
- // for clients that don't support JS
- if( opts.children || (opts.initAjax && opts.initAjax.url) || opts.initId )
- $(divTree).empty();
-*/
- // Create the DynaTree object
- this.tree = new DynaTree(this);
- this.tree._load();
- this.tree.logDebug("Dynatree._init(): done.");
- },
-
- bind: function() {
- // Prevent duplicate binding
- this.unbind();
-
- var eventNames = "click.dynatree dblclick.dynatree";
- if( this.options.keyboard ){
- // Note: leading ' '!
- eventNames += " keypress.dynatree keydown.dynatree";
- }
- this.element.bind(eventNames, function(event){
- var dtnode = $.ui.dynatree.getNode(event.target);
- if( !dtnode ){
- return true; // Allow bubbling of other events
- }
- var tree = dtnode.tree;
- var o = tree.options;
- tree.logDebug("event(%s): dtnode: %s", event.type, dtnode);
- var prevPhase = tree.phase;
- tree.phase = "userEvent";
- try {
- switch(event.type) {
- case "click":
- return ( o.onClick && o.onClick.call(tree, dtnode, event)===false ) ? false : dtnode._onClick(event);
- case "dblclick":
- return ( o.onDblClick && o.onDblClick.call(tree, dtnode, event)===false ) ? false : dtnode._onDblClick(event);
- case "keydown":
- return ( o.onKeydown && o.onKeydown.call(tree, dtnode, event)===false ) ? false : dtnode._onKeydown(event);
- case "keypress":
- return ( o.onKeypress && o.onKeypress.call(tree, dtnode, event)===false ) ? false : dtnode._onKeypress(event);
- }
- } catch(e) {
- var _ = null; // issue 117
- tree.logWarning("bind(%o): dtnode: %o, error: %o", event, dtnode, e);
- } finally {
- tree.phase = prevPhase;
- }
- });
-
- // focus/blur don't bubble, i.e. are not delegated to parent <div> tags,
- // so we use the addEventListener capturing phase.
- // See http://www.howtocreate.co.uk/tutorials/javascript/domevents
- function __focusHandler(event) {
- // Handles blur and focus.
- // Fix event for IE:
- // doesn't pass JSLint:
-// event = arguments[0] = $.event.fix( event || window.event );
- // what jQuery does:
-// var args = jQuery.makeArray( arguments );
-// event = args[0] = jQuery.event.fix( event || window.event );
- event = $.event.fix( event || window.event );
- var dtnode = $.ui.dynatree.getNode(event.target);
- return dtnode ? dtnode._onFocus(event) : false;
- }
- var div = this.tree.divTree;
-
- if( div.addEventListener ) {
- div.addEventListener("focus", __focusHandler, true);
- div.addEventListener("blur", __focusHandler, true);
- } else {
- div.onfocusin = div.onfocusout = __focusHandler;
- }
- // EVENTS
- // disable click if event is configured to something else
-// if (!(/^click/).test(o.event))
-// this.$tabs.bind("click.tabs", function() { return false; });
-
- },
-
- unbind: function() {
- this.element.unbind(".dynatree");
- },
-
-/* TODO: we could handle option changes during runtime here (maybe to re-render, ...)
- setData: function(key, value) {
- this.tree.logDebug("dynatree.setData('" + key + "', '" + value + "')");
- },
-*/
- enable: function() {
- this.bind();
- // Call default disable(): remove -disabled from css:
- $.Widget.prototype.enable.apply(this, arguments);
- },
-
- disable: function() {
- this.unbind();
- // Call default disable(): add -disabled to css:
- $.Widget.prototype.disable.apply(this, arguments);
- },
-
- // --- getter methods (i.e. NOT returning a reference to $)
- getTree: function() {
- return this.tree;
- },
-
- getRoot: function() {
- return this.tree.getRoot();
- },
-
- getActiveNode: function() {
- return this.tree.getActiveNode();
- },
-
- getSelectedNodes: function() {
- return this.tree.getSelectedNodes();
- },
-
- // ------------------------------------------------------------------------
- lastentry: undefined
-});
-
-
-// The following methods return a value (thus breaking the jQuery call chain):
-if(versionCompare($.ui.version, "1.8") < 0){
-//if( parseFloat($.ui.version) < 1.8 ) {
- $.ui.dynatree.getter = "getTree getRoot getActiveNode getSelectedNodes";
-}
-
-/*******************************************************************************
- * Tools in ui.dynatree namespace
- */
-$.ui.dynatree.version = "$Version: 1.2.4$";
-
-/**
- * Return a DynaTreeNode object for a given DOM element
- */
-$.ui.dynatree.getNode = function(el) {
- if(el instanceof DynaTreeNode){
- return el; // el already was a DynaTreeNode
- }
- if(el.selector !== undefined){
- el = el[0]; // el was a jQuery object: use the DOM element
- }
- // TODO: for some reason $el.parents("[dtnode]") does not work (jQuery 1.6.1)
- // maybe, because dtnode is a property, not an attribute
- while( el ) {
- if(el.dtnode) {
- return el.dtnode;
- }
- el = el.parentNode;
- }
- return null;
-/*
- var $el = el.selector === undefined ? $(el) : el,
-// parent = $el.closest("[dtnode]"),
-// parent = $el.parents("[dtnode]").first(),
- useProp = (typeof $el.prop == "function"),
- node;
- $el.parents().each(function(){
- node = useProp ? $(this).prop("dtnode") : $(this).attr("dtnode");
- if(node){
- return false;
- }
- });
- return node;
-*/
-};
-
-/**Return persistence information from cookies.*/
-$.ui.dynatree.getPersistData = DynaTreeStatus._getTreePersistData;
-
-/*******************************************************************************
- * Plugin default options:
- */
-$.ui.dynatree.prototype.options = {
- title: "Dynatree", // Tree's name (only used for debug output)
- minExpandLevel: 1, // 1: root node is not collapsible
- imagePath: null, // Path to a folder containing icons. Defaults to 'skin/' subdirectory.
- children: null, // Init tree structure from this object array.
- initId: null, // Init tree structure from a <ul> element with this ID.
- initAjax: null, // Ajax options used to initialize the tree strucuture.
- autoFocus: true, // Set focus to first child, when expanding or lazy-loading.
- keyboard: true, // Support keyboard navigation.
- persist: false, // Persist expand-status to a cookie
- autoCollapse: false, // Automatically collapse all siblings, when a node is expanded.
- clickFolderMode: 3, // 1:activate, 2:expand, 3:activate and expand
- activeVisible: true, // Make sure, active nodes are visible (expanded).
- checkbox: false, // Show checkboxes.
- selectMode: 2, // 1:single, 2:multi, 3:multi-hier
- fx: null, // Animations, e.g. null or { height: "toggle", duration: 200 }
- noLink: false, // Use <span> instead of <a> tags for all nodes
- // Low level event handlers: onEvent(dtnode, event): return false, to stop default processing
- onClick: null, // null: generate focus, expand, activate, select events.
- onDblClick: null, // (No default actions.)
- onKeydown: null, // null: generate keyboard navigation (focus, expand, activate).
- onKeypress: null, // (No default actions.)
- onFocus: null, // null: set focus to node.
- onBlur: null, // null: remove focus from node.
-
- // Pre-event handlers onQueryEvent(flag, dtnode): return false, to stop processing
- onQueryActivate: null, // Callback(flag, dtnode) before a node is (de)activated.
- onQuerySelect: null, // Callback(flag, dtnode) before a node is (de)selected.
- onQueryExpand: null, // Callback(flag, dtnode) before a node is expanded/collpsed.
-
- // High level event handlers
- onPostInit: null, // Callback(isReloading, isError) when tree was (re)loaded.
- onActivate: null, // Callback(dtnode) when a node is activated.
- onDeactivate: null, // Callback(dtnode) when a node is deactivated.
- onSelect: null, // Callback(flag, dtnode) when a node is (de)selected.
- onExpand: null, // Callback(flag, dtnode) when a node is expanded/collapsed.
- onLazyRead: null, // Callback(dtnode) when a lazy node is expanded for the first time.
- onCustomRender: null, // Callback(dtnode) before a node is rendered. Return a HTML string to override.
- onCreate: null, // Callback(dtnode, nodeSpan) after a node was rendered for the first time.
- onRender: null, // Callback(dtnode, nodeSpan) after a node was rendered.
- // postProcess is similar to the standard dataFilter hook,
- // but it is also called for JSONP
- postProcess: null, // Callback(data, dataType) before an Ajax result is passed to dynatree
-
- // Drag'n'drop support
- dnd: {
- // Make tree nodes draggable:
- onDragStart: null, // Callback(sourceNode), return true, to enable dnd
- onDragStop: null, // Callback(sourceNode)
-// helper: null,
- // Make tree nodes accept draggables
- autoExpandMS: 1000, // Expand nodes after n milliseconds of hovering.
- preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
- onDragEnter: null, // Callback(targetNode, sourceNode)
- onDragOver: null, // Callback(targetNode, sourceNode, hitMode)
- onDrop: null, // Callback(targetNode, sourceNode, hitMode)
- onDragLeave: null // Callback(targetNode, sourceNode)
- },
- ajaxDefaults: { // Used by initAjax option
- cache: false, // false: Append random '_' argument to the request url to prevent caching.
- timeout: 0, // >0: Make sure we get an ajax error for invalid URLs
- dataType: "json" // Expect json format and pass json object to callbacks.
- },
- strings: {
- loading: "Loading&#8230;",
- loadError: "Load error!"
- },
- generateIds: false, // Generate id attributes like <span id='dynatree-id-KEY'>
- idPrefix: "dynatree-id-", // Used to generate node id's like <span id="dynatree-id-<key>">.
- keyPathSeparator: "/", // Used by node.getKeyPath() and tree.loadKeyPath().
-// cookieId: "dynatree-cookie", // Choose a more unique name, to allow multiple trees.
- cookieId: "dynatree", // Choose a more unique name, to allow multiple trees.
- cookie: {
- expires: null //7, // Days or Date; null: session cookie
-// path: "/", // Defaults to current page
-// domain: "jquery.com",
-// secure: true
- },
- // Class names used, when rendering the HTML markup.
- // Note: if only single entries are passed for options.classNames, all other
- // values are still set to default.
- classNames: {
- container: "dynatree-container",
- node: "dynatree-node",
- folder: "dynatree-folder",
-// document: "dynatree-document",
-
- empty: "dynatree-empty",
- vline: "dynatree-vline",
- expander: "dynatree-expander",
- connector: "dynatree-connector",
- checkbox: "dynatree-checkbox",
- nodeIcon: "dynatree-icon",
- title: "dynatree-title",
- noConnector: "dynatree-no-connector",
-
- nodeError: "dynatree-statusnode-error",
- nodeWait: "dynatree-statusnode-wait",
- hidden: "dynatree-hidden",
- combinedExpanderPrefix: "dynatree-exp-",
- combinedIconPrefix: "dynatree-ico-",
- nodeLoading: "dynatree-loading",
-// disabled: "dynatree-disabled",
- hasChildren: "dynatree-has-children",
- active: "dynatree-active",
- selected: "dynatree-selected",
- expanded: "dynatree-expanded",
- lazy: "dynatree-lazy",
- focused: "dynatree-focused",
- partsel: "dynatree-partsel",
- lastsib: "dynatree-lastsib"
- },
- debugLevel: 1,
-
- // ------------------------------------------------------------------------
- lastentry: undefined
-};
-//
-if(versionCompare($.ui.version, "1.8") < 0){
-//if( parseFloat($.ui.version) < 1.8 ) {
- $.ui.dynatree.defaults = $.ui.dynatree.prototype.options;
-}
-
-/*******************************************************************************
- * Reserved data attributes for a tree node.
- */
-$.ui.dynatree.nodedatadefaults = {
- title: null, // (required) Displayed name of the node (html is allowed here)
- key: null, // May be used with activate(), select(), find(), ...
- isFolder: false, // Use a folder icon. Also the node is expandable but not selectable.
- isLazy: false, // Call onLazyRead(), when the node is expanded for the first time to allow for delayed creation of children.
- tooltip: null, // Show this popup text.
- href: null, // Added to the generated <a> tag.
- icon: null, // Use a custom image (filename relative to tree.options.imagePath). 'null' for default icon, 'false' for no icon.
- addClass: null, // Class name added to the node's span tag.
- noLink: false, // Use <span> instead of <a> tag for this node
- activate: false, // Initial active status.
- focus: false, // Initial focused status.
- expand: false, // Initial expanded status.
- select: false, // Initial selected status.
- hideCheckbox: false, // Suppress checkbox display for this node.
- unselectable: false, // Prevent selection.
-// disabled: false,
- // The following attributes are only valid if passed to some functions:
- children: null, // Array of child nodes.
- // NOTE: we can also add custom attributes here.
- // This may then also be used in the onActivate(), onSelect() or onLazyTree() callbacks.
- // ------------------------------------------------------------------------
- lastentry: undefined
-};
-
-/*******************************************************************************
- * Drag and drop support
- */
-function _initDragAndDrop(tree) {
- var dnd = tree.options.dnd || null;
- // Register 'connectToDynatree' option with ui.draggable
- if(dnd && (dnd.onDragStart || dnd.onDrop)) {
- _registerDnd();
- }
- // Attach ui.draggable to this Dynatree instance
- if(dnd && dnd.onDragStart ) {
- tree.$tree.draggable({
- addClasses: false,
- appendTo: "body",
- containment: false,
- delay: 0,
- distance: 4,
- revert: false,
- scroll: true, // issue 244: enable scrolling (if ul.dynatree-container)
- scrollSpeed: 7,
- scrollSensitivity: 10,
- // Delegate draggable.start, drag, and stop events to our handler
- connectToDynatree: true,
- // Let source tree create the helper element
- helper: function(event) {
- var sourceNode = $.ui.dynatree.getNode(event.target);
- if(!sourceNode){ // issue 211
- return "<div></div>";
- }
- return sourceNode.tree._onDragEvent("helper", sourceNode, null, event, null, null);
- },
- start: function(event, ui) {
- // See issues 211, 268, 278
-// var sourceNode = $.ui.dynatree.getNode(event.target);
- var sourceNode = ui.helper.data("dtSourceNode");
- return !!sourceNode; // Abort dragging if no Node could be found
- },
- _last: null
- });
- }
- // Attach ui.droppable to this Dynatree instance
- if(dnd && dnd.onDrop) {
- tree.$tree.droppable({
- addClasses: false,
- tolerance: "intersect",
- greedy: false,
- _last: null
- });
- }
-}
-
-//--- Extend ui.draggable event handling --------------------------------------
-var didRegisterDnd = false;
-var _registerDnd = function() {
- if(didRegisterDnd){
- return;
- }
- // Register proxy-functions for draggable.start/drag/stop
- $.ui.plugin.add("draggable", "connectToDynatree", {
- start: function(event, ui) {
- // issue 386
- var draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
- sourceNode = ui.helper.data("dtSourceNode") || null;
-// logMsg("draggable-connectToDynatree.start, %s", sourceNode);
-// logMsg(" this: %o", this);
-// logMsg(" event: %o", event);
-// logMsg(" draggable: %o", draggable);
-// logMsg(" ui: %o", ui);
-
- if(sourceNode) {
- // Adjust helper offset, so cursor is slightly outside top/left corner
-// draggable.offset.click.top -= event.target.offsetTop;
-// draggable.offset.click.left -= event.target.offsetLeft;
- draggable.offset.click.top = -2;
- draggable.offset.click.left = + 16;
-// logMsg(" draggable2: %o", draggable);
-// logMsg(" draggable.offset.click FIXED: %s/%s", draggable.offset.click.left, draggable.offset.click.top);
- // Trigger onDragStart event
- // TODO: when called as connectTo..., the return value is ignored(?)
- return sourceNode.tree._onDragEvent("start", sourceNode, null, event, ui, draggable);
- }
- },
- drag: function(event, ui) {
- // issue 386
- var draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
- sourceNode = ui.helper.data("dtSourceNode") || null,
- prevTargetNode = ui.helper.data("dtTargetNode") || null,
- targetNode = $.ui.dynatree.getNode(event.target);
-// logMsg("$.ui.dynatree.getNode(%o): %s", event.target, targetNode);
-// logMsg("connectToDynatree.drag: helper: %o", ui.helper[0]);
- if(event.target && !targetNode){
- // We got a drag event, but the targetNode could not be found
- // at the event location. This may happen,
- // 1. if the mouse jumped over the drag helper,
- // 2. or if non-dynatree element is dragged
- // We ignore it:
- var isHelper = $(event.target).closest("div.dynatree-drag-helper,#dynatree-drop-marker").length > 0;
- if(isHelper){
-// logMsg("Drag event over helper: ignored.");
- return;
- }
- }
-// logMsg("draggable-connectToDynatree.drag: targetNode(from event): %s, dtTargetNode: %s", targetNode, ui.helper.data("dtTargetNode"));
- ui.helper.data("dtTargetNode", targetNode);
- // Leaving a tree node
- if(prevTargetNode && prevTargetNode !== targetNode ) {
- prevTargetNode.tree._onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
- }
- if(targetNode){
- if(!targetNode.tree.options.dnd.onDrop) {
- // not enabled as drop target
-// noop(); // Keep JSLint happy
- } else if(targetNode === prevTargetNode) {
- // Moving over same node
- targetNode.tree._onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
- }else{
- // Entering this node first time
- targetNode.tree._onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
- }
- }
- // else go ahead with standard event handling
- },
- stop: function(event, ui) {
- // issue 386
- var draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
- sourceNode = ui.helper.data("dtSourceNode") || null,
- targetNode = ui.helper.data("dtTargetNode") || null,
- mouseDownEvent = draggable._mouseDownEvent,
- eventType = event.type,
- dropped = (eventType == "mouseup" && event.which == 1);
- logMsg("draggable-connectToDynatree.stop: targetNode(from event): %s, dtTargetNode: %s", targetNode, ui.helper.data("dtTargetNode"));
-// logMsg("draggable-connectToDynatree.stop, %s", sourceNode);
-// logMsg(" type: %o, downEvent: %o, upEvent: %o", eventType, mouseDownEvent, event);
-// logMsg(" targetNode: %o", targetNode);
- if(!dropped){
- logMsg("Drag was cancelled");
- }
- if(targetNode) {
- if(dropped){
- targetNode.tree._onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
- }
- targetNode.tree._onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
- }
- if(sourceNode){
- sourceNode.tree._onDragEvent("stop", sourceNode, null, event, ui, draggable);
- }
- }
- });
- didRegisterDnd = true;
-};
-
-// ---------------------------------------------------------------------------
-}(jQuery));
diff --git a/SemanticForms/libs/jquery.fancybox.js b/SemanticForms/libs/jquery.fancybox.js
deleted file mode 100644
index 68d28659..00000000
--- a/SemanticForms/libs/jquery.fancybox.js
+++ /dev/null
@@ -1,1152 +0,0 @@
-/*
- * FancyBox - jQuery Plugin
- * Simple and fancy lightbox alternative
- *
- * Examples and documentation at: http://fancybox.net
- *
- * Copyright (c) 2008 - 2010 Janis Skarnelis
- * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
- *
- * Version: 1.3.4 (11/11/2010)
- * Requires: jQuery v1.3+
- *
- * Dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- */
-
-;(function($) {
- var tmp, loading, overlay, wrap, outer, content, close, title, nav_left, nav_right,
-
- selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [],
-
- ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i,
-
- loadingTimer, loadingFrame = 1,
-
- titleHeight = 0, titleStr = '', start_pos, final_pos, busy = false, fx = $.extend($('<div/>')[0], { prop: 0 }),
-
- isIE6 = $.browser.msie && $.browser.version < 7 && !window.XMLHttpRequest,
-
- /*
- * Private methods
- */
-
- _abort = function() {
- loading.hide();
-
- imgPreloader.onerror = imgPreloader.onload = null;
-
- if (ajaxLoader) {
- ajaxLoader.abort();
- }
-
- tmp.empty();
- },
-
- _error = function() {
- if (false === selectedOpts.onError(selectedArray, selectedIndex, selectedOpts)) {
- loading.hide();
- busy = false;
- return;
- }
-
- selectedOpts.titleShow = false;
-
- selectedOpts.width = 'auto';
- selectedOpts.height = 'auto';
-
- tmp.html( '<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>' );
-
- _process_inline();
- },
-
- _start = function() {
- var obj = selectedArray[ selectedIndex ],
- href,
- type,
- title,
- str,
- emb,
- ret;
-
- _abort();
-
- selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox')));
-
- ret = selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts);
-
- if (ret === false) {
- busy = false;
- return;
- } else if (typeof ret == 'object') {
- selectedOpts = $.extend(selectedOpts, ret);
- }
-
- title = selectedOpts.title || (obj.nodeName ? $(obj).attr('title') : obj.title) || '';
-
- if (obj.nodeName && !selectedOpts.orig) {
- selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj);
- }
-
- if (title === '' && selectedOpts.orig && selectedOpts.titleFromAlt) {
- title = selectedOpts.orig.attr('alt');
- }
-
- href = selectedOpts.href || (obj.nodeName ? $(obj).attr('href') : obj.href) || null;
-
- if ((/^(?:javascript)/i).test(href) || href == '#') {
- href = null;
- }
-
- if (selectedOpts.type) {
- type = selectedOpts.type;
-
- if (!href) {
- href = selectedOpts.content;
- }
-
- } else if (selectedOpts.content) {
- type = 'html';
-
- } else if (href) {
- if (href.match(imgRegExp)) {
- type = 'image';
-
- } else if (href.match(swfRegExp)) {
- type = 'swf';
-
- } else if ($(obj).hasClass("iframe")) {
- type = 'iframe';
-
- } else if (href.indexOf("#") === 0) {
- type = 'inline';
-
- } else {
- type = 'ajax';
- }
- }
-
- if (!type) {
- _error();
- return;
- }
-
- if (type == 'inline') {
- obj = href.substr(href.indexOf("#"));
- type = $(obj).length > 0 ? 'inline' : 'ajax';
- }
-
- selectedOpts.type = type;
- selectedOpts.href = href;
- selectedOpts.title = title;
-
- if (selectedOpts.autoDimensions) {
- if (selectedOpts.type == 'html' || selectedOpts.type == 'inline' || selectedOpts.type == 'ajax') {
- selectedOpts.width = 'auto';
- selectedOpts.height = 'auto';
- } else {
- selectedOpts.autoDimensions = false;
- }
- }
-
- if (selectedOpts.modal) {
- selectedOpts.overlayShow = true;
- selectedOpts.hideOnOverlayClick = false;
- selectedOpts.hideOnContentClick = false;
- selectedOpts.enableEscapeButton = false;
- selectedOpts.showCloseButton = false;
- }
-
- selectedOpts.padding = parseInt(selectedOpts.padding, 10);
- selectedOpts.margin = parseInt(selectedOpts.margin, 10);
-
- tmp.css('padding', (selectedOpts.padding + selectedOpts.margin));
-
- $('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() {
- $(this).replaceWith(content.children());
- });
-
- switch (type) {
- case 'html' :
- tmp.html( selectedOpts.content );
- _process_inline();
- break;
-
- case 'inline' :
- if ( $(obj).parent().is('#fancybox-content') === true) {
- busy = false;
- return;
- }
-
- $('<div class="fancybox-inline-tmp" />')
- .hide()
- .insertBefore( $(obj) )
- .bind('fancybox-cleanup', function() {
- $(this).replaceWith(content.children());
- }).bind('fancybox-cancel', function() {
- $(this).replaceWith(tmp.children());
- });
-
- $(obj).appendTo(tmp);
-
- _process_inline();
- break;
-
- case 'image':
- busy = false;
-
- $.fancybox.showActivity();
-
- imgPreloader = new Image();
-
- imgPreloader.onerror = function() {
- _error();
- };
-
- imgPreloader.onload = function() {
- busy = true;
-
- imgPreloader.onerror = imgPreloader.onload = null;
-
- _process_image();
- };
-
- imgPreloader.src = href;
- break;
-
- case 'swf':
- selectedOpts.scrolling = 'no';
-
- str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>';
- emb = '';
-
- $.each(selectedOpts.swf, function(name, val) {
- str += '<param name="' + name + '" value="' + val + '"></param>';
- emb += ' ' + name + '="' + val + '"';
- });
-
- str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>';
-
- tmp.html(str);
-
- _process_inline();
- break;
-
- case 'ajax':
- busy = false;
-
- $.fancybox.showActivity();
-
- selectedOpts.ajax.win = selectedOpts.ajax.success;
-
- ajaxLoader = $.ajax($.extend({}, selectedOpts.ajax, {
- url : href,
- data : selectedOpts.ajax.data || {},
- error : function(XMLHttpRequest, textStatus, errorThrown) {
- if ( XMLHttpRequest.status > 0 ) {
- _error();
- }
- },
- success : function(data, textStatus, XMLHttpRequest) {
- var o = typeof XMLHttpRequest == 'object' ? XMLHttpRequest : ajaxLoader;
- if (o.status == 200) {
- if ( typeof selectedOpts.ajax.win == 'function' ) {
- ret = selectedOpts.ajax.win(href, data, textStatus, XMLHttpRequest);
-
- if (ret === false) {
- loading.hide();
- return;
- } else if (typeof ret == 'string' || typeof ret == 'object') {
- data = ret;
- }
- }
-
- tmp.html( data );
- _process_inline();
- }
- }
- }));
-
- break;
-
- case 'iframe':
- _show();
- break;
- }
- },
-
- _process_inline = function() {
- var
- w = selectedOpts.width,
- h = selectedOpts.height;
-
- if (w.toString().indexOf('%') > -1) {
- w = parseInt( ($(window).width() - (selectedOpts.margin * 2)) * parseFloat(w) / 100, 10) + 'px';
-
- } else {
- w = w == 'auto' ? 'auto' : w + 'px';
- }
-
- if (h.toString().indexOf('%') > -1) {
- h = parseInt( ($(window).height() - (selectedOpts.margin * 2)) * parseFloat(h) / 100, 10) + 'px';
-
- } else {
- h = h == 'auto' ? 'auto' : h + 'px';
- }
-
- tmp.wrapInner('<div style="width:' + w + ';height:' + h + ';overflow: ' + (selectedOpts.scrolling == 'auto' ? 'auto' : (selectedOpts.scrolling == 'yes' ? 'scroll' : 'hidden')) + ';position:relative;"></div>');
-
- selectedOpts.width = tmp.width();
- selectedOpts.height = tmp.height();
-
- _show();
- },
-
- _process_image = function() {
- selectedOpts.width = imgPreloader.width;
- selectedOpts.height = imgPreloader.height;
-
- $("<img />").attr({
- 'id' : 'fancybox-img',
- 'src' : imgPreloader.src,
- 'alt' : selectedOpts.title
- }).appendTo( tmp );
-
- _show();
- },
-
- _show = function() {
- var pos, equal;
-
- loading.hide();
-
- if (wrap.is(":visible") && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) {
- $.event.trigger('fancybox-cancel');
-
- busy = false;
- return;
- }
-
- busy = true;
-
- $(content.add( overlay )).unbind();
-
- $(window).unbind("resize.fb scroll.fb");
- $(document).unbind('keydown.fb');
-
- if (wrap.is(":visible") && currentOpts.titlePosition !== 'outside') {
- wrap.css('height', wrap.height());
- }
-
- currentArray = selectedArray;
- currentIndex = selectedIndex;
- currentOpts = selectedOpts;
-
- if (currentOpts.overlayShow) {
- overlay.css({
- 'background-color' : currentOpts.overlayColor,
- 'opacity' : currentOpts.overlayOpacity,
- 'cursor' : currentOpts.hideOnOverlayClick ? 'pointer' : 'auto',
- 'height' : $(document).height()
- });
-
- if (!overlay.is(':visible')) {
- if (isIE6) {
- $('select:not(#fancybox-tmp select)').filter(function() {
- return this.style.visibility !== 'hidden';
- }).css({'visibility' : 'hidden'}).one('fancybox-cleanup', function() {
- this.style.visibility = 'inherit';
- });
- }
-
- overlay.show();
- }
- } else {
- overlay.hide();
- }
-
- final_pos = _get_zoom_to();
-
- _process_title();
-
- if (wrap.is(":visible")) {
- $( close.add( nav_left ).add( nav_right ) ).hide();
-
- pos = wrap.position();
-
- start_pos = {
- top : pos.top,
- left : pos.left,
- width : wrap.width(),
- height : wrap.height()
- };
-
- equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height);
-
- content.fadeTo(currentOpts.changeFade, 0.3, function() {
- var finish_resizing = function() {
- content.html( tmp.contents() ).fadeTo(currentOpts.changeFade, 1, _finish);
- };
-
- $.event.trigger('fancybox-change');
-
- content
- .empty()
- .removeAttr('filter')
- .css({
- 'border-width' : currentOpts.padding,
- 'width' : final_pos.width - currentOpts.padding * 2,
- 'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2
- });
-
- if (equal) {
- finish_resizing();
-
- } else {
- fx.prop = 0;
-
- $(fx).animate({prop: 1}, {
- duration : currentOpts.changeSpeed,
- easing : currentOpts.easingChange,
- step : _draw,
- complete : finish_resizing
- });
- }
- });
-
- return;
- }
-
- wrap.removeAttr("style");
-
- content.css('border-width', currentOpts.padding);
-
- if (currentOpts.transitionIn == 'elastic') {
- start_pos = _get_zoom_from();
-
- content.html( tmp.contents() );
-
- wrap.show();
-
- if (currentOpts.opacity) {
- final_pos.opacity = 0;
- }
-
- fx.prop = 0;
-
- $(fx).animate({prop: 1}, {
- duration : currentOpts.speedIn,
- easing : currentOpts.easingIn,
- step : _draw,
- complete : _finish
- });
-
- return;
- }
-
- if (currentOpts.titlePosition == 'inside' && titleHeight > 0) {
- title.show();
- }
-
- content
- .css({
- 'width' : final_pos.width - currentOpts.padding * 2,
- 'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2
- })
- .html( tmp.contents() );
-
- wrap
- .css(final_pos)
- .fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish );
- },
-
- _format_title = function(title) {
- if (title && title.length) {
- if (currentOpts.titlePosition == 'float') {
- return '<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">' + title + '</td><td id="fancybox-title-float-right"></td></tr></table>';
- }
-
- return '<div id="fancybox-title-' + currentOpts.titlePosition + '">' + title + '</div>';
- }
-
- return false;
- },
-
- _process_title = function() {
- titleStr = currentOpts.title || '';
- titleHeight = 0;
-
- title
- .empty()
- .removeAttr('style')
- .removeClass();
-
- if (currentOpts.titleShow === false) {
- title.hide();
- return;
- }
-
- titleStr = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(titleStr, currentArray, currentIndex, currentOpts) : _format_title(titleStr);
-
- if (!titleStr || titleStr === '') {
- title.hide();
- return;
- }
-
- title
- .addClass('fancybox-title-' + currentOpts.titlePosition)
- .html( titleStr )
- .appendTo( 'body' )
- .show();
-
- switch (currentOpts.titlePosition) {
- case 'inside':
- title
- .css({
- 'width' : final_pos.width - (currentOpts.padding * 2),
- 'marginLeft' : currentOpts.padding,
- 'marginRight' : currentOpts.padding
- });
-
- titleHeight = title.outerHeight(true);
-
- title.appendTo( outer );
-
- final_pos.height += titleHeight;
- break;
-
- case 'over':
- title
- .css({
- 'marginLeft' : currentOpts.padding,
- 'width' : final_pos.width - (currentOpts.padding * 2),
- 'bottom' : currentOpts.padding
- })
- .appendTo( outer );
- break;
-
- case 'float':
- title
- .css('left', parseInt((title.width() - final_pos.width - 40)/ 2, 10) * -1)
- .appendTo( wrap );
- break;
-
- default:
- title
- .css({
- 'width' : final_pos.width - (currentOpts.padding * 2),
- 'paddingLeft' : currentOpts.padding,
- 'paddingRight' : currentOpts.padding
- })
- .appendTo( wrap );
- break;
- }
-
- title.hide();
- },
-
- _set_navigation = function() {
- if (currentOpts.enableEscapeButton || currentOpts.enableKeyboardNav) {
- $(document).bind('keydown.fb', function(e) {
- if (e.keyCode == 27 && currentOpts.enableEscapeButton) {
- e.preventDefault();
- $.fancybox.close();
-
- } else if ((e.keyCode == 37 || e.keyCode == 39) && currentOpts.enableKeyboardNav && e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA' && e.target.tagName !== 'SELECT') {
- e.preventDefault();
- $.fancybox[ e.keyCode == 37 ? 'prev' : 'next']();
- }
- });
- }
-
- if (!currentOpts.showNavArrows) {
- nav_left.hide();
- nav_right.hide();
- return;
- }
-
- if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) {
- nav_left.show();
- }
-
- if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) {
- nav_right.show();
- }
- },
-
- _finish = function () {
- if (!$.support.opacity) {
- content.get(0).style.removeAttribute('filter');
- wrap.get(0).style.removeAttribute('filter');
- }
-
- if (selectedOpts.autoDimensions) {
- content.css('height', 'auto');
- }
-
- wrap.css('height', 'auto');
-
- if (titleStr && titleStr.length) {
- title.show();
- }
-
- if (currentOpts.showCloseButton) {
- close.show();
- }
-
- _set_navigation();
-
- if (currentOpts.hideOnContentClick) {
- content.bind('click', $.fancybox.close);
- }
-
- if (currentOpts.hideOnOverlayClick) {
- overlay.bind('click', $.fancybox.close);
- }
-
- $(window).bind("resize.fb", $.fancybox.resize);
-
- if (currentOpts.centerOnScroll) {
- $(window).bind("scroll.fb", $.fancybox.center);
- }
-
- if (currentOpts.type == 'iframe') {
- $('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" ' + ($.browser.msie ? 'allowtransparency="true""' : '') + ' scrolling="' + selectedOpts.scrolling + '" src="' + currentOpts.href + '"></iframe>').appendTo(content);
- }
-
- wrap.show();
-
- busy = false;
-
- $.fancybox.center();
-
- currentOpts.onComplete(currentArray, currentIndex, currentOpts);
-
- _preload_images();
- },
-
- _preload_images = function() {
- var href,
- objNext;
-
- if ((currentArray.length -1) > currentIndex) {
- href = currentArray[ currentIndex + 1 ].href;
-
- if (typeof href !== 'undefined' && href.match(imgRegExp)) {
- objNext = new Image();
- objNext.src = href;
- }
- }
-
- if (currentIndex > 0) {
- href = currentArray[ currentIndex - 1 ].href;
-
- if (typeof href !== 'undefined' && href.match(imgRegExp)) {
- objNext = new Image();
- objNext.src = href;
- }
- }
- },
-
- _draw = function(pos) {
- var dim = {
- width : parseInt(start_pos.width + (final_pos.width - start_pos.width) * pos, 10),
- height : parseInt(start_pos.height + (final_pos.height - start_pos.height) * pos, 10),
-
- top : parseInt(start_pos.top + (final_pos.top - start_pos.top) * pos, 10),
- left : parseInt(start_pos.left + (final_pos.left - start_pos.left) * pos, 10)
- };
-
- if (typeof final_pos.opacity !== 'undefined') {
- dim.opacity = pos < 0.5 ? 0.5 : pos;
- }
-
- wrap.css(dim);
-
- content.css({
- 'width' : dim.width - currentOpts.padding * 2,
- 'height' : dim.height - (titleHeight * pos) - currentOpts.padding * 2
- });
- },
-
- _get_viewport = function() {
- return [
- $(window).width() - (currentOpts.margin * 2),
- $(window).height() - (currentOpts.margin * 2),
- $(document).scrollLeft() + currentOpts.margin,
- $(document).scrollTop() + currentOpts.margin
- ];
- },
-
- _get_zoom_to = function () {
- var view = _get_viewport(),
- to = {},
- resize = currentOpts.autoScale,
- double_padding = currentOpts.padding * 2,
- ratio;
-
- if (currentOpts.width.toString().indexOf('%') > -1) {
- to.width = parseInt((view[0] * parseFloat(currentOpts.width)) / 100, 10);
- } else {
- to.width = currentOpts.width + double_padding;
- }
-
- if (currentOpts.height.toString().indexOf('%') > -1) {
- to.height = parseInt((view[1] * parseFloat(currentOpts.height)) / 100, 10);
- } else {
- to.height = currentOpts.height + double_padding;
- }
-
- if (resize && (to.width > view[0] || to.height > view[1])) {
- if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') {
- ratio = (currentOpts.width ) / (currentOpts.height );
-
- if ((to.width ) > view[0]) {
- to.width = view[0];
- to.height = parseInt(((to.width - double_padding) / ratio) + double_padding, 10);
- }
-
- if ((to.height) > view[1]) {
- to.height = view[1];
- to.width = parseInt(((to.height - double_padding) * ratio) + double_padding, 10);
- }
-
- } else {
- to.width = Math.min(to.width, view[0]);
- to.height = Math.min(to.height, view[1]);
- }
- }
-
- to.top = parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - to.height - 40) * 0.5)), 10);
- to.left = parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - to.width - 40) * 0.5)), 10);
-
- return to;
- },
-
- _get_obj_pos = function(obj) {
- var pos = obj.offset();
-
- pos.top += parseInt( obj.css('paddingTop'), 10 ) || 0;
- pos.left += parseInt( obj.css('paddingLeft'), 10 ) || 0;
-
- pos.top += parseInt( obj.css('border-top-width'), 10 ) || 0;
- pos.left += parseInt( obj.css('border-left-width'), 10 ) || 0;
-
- pos.width = obj.width();
- pos.height = obj.height();
-
- return pos;
- },
-
- _get_zoom_from = function() {
- var orig = selectedOpts.orig ? $(selectedOpts.orig) : false,
- from = {},
- pos,
- view;
-
- if (orig && orig.length) {
- pos = _get_obj_pos(orig);
-
- from = {
- width : pos.width + (currentOpts.padding * 2),
- height : pos.height + (currentOpts.padding * 2),
- top : pos.top - currentOpts.padding - 20,
- left : pos.left - currentOpts.padding - 20
- };
-
- } else {
- view = _get_viewport();
-
- from = {
- width : currentOpts.padding * 2,
- height : currentOpts.padding * 2,
- top : parseInt(view[3] + view[1] * 0.5, 10),
- left : parseInt(view[2] + view[0] * 0.5, 10)
- };
- }
-
- return from;
- },
-
- _animate_loading = function() {
- if (!loading.is(':visible')){
- clearInterval(loadingTimer);
- return;
- }
-
- $('div', loading).css('top', (loadingFrame * -40) + 'px');
-
- loadingFrame = (loadingFrame + 1) % 12;
- };
-
- /**
- * Public methods
- */
-
- $.fn.fancybox = function(options) {
- if (!$(this).length) {
- return this;
- }
-
- $(this)
- .data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {})))
- .unbind('click.fb')
- .bind('click.fb', function(e) {
- e.preventDefault();
-
- if (busy) {
- return;
- }
-
- busy = true;
-
- $(this).blur();
-
- selectedArray = [];
- selectedIndex = 0;
-
- var rel = $(this).attr('rel') || '';
-
- if (!rel || rel === '' || rel === 'nofollow') {
- selectedArray.push(this);
-
- } else {
- selectedArray = $("a[rel=" + rel + "], area[rel=" + rel + "]");
- selectedIndex = selectedArray.index( this );
- }
-
- _start();
- });
-
- return this;
- };
-
- $.fancybox = function(obj) {
- var opts;
-
- if (busy) {
- return;
- }
-
- busy = true;
- opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {};
-
- selectedArray = [];
- selectedIndex = parseInt(opts.index, 10) || 0;
-
- if ($.isArray(obj)) {
- for (var i = 0, j = obj.length; i < j; i++) {
- if (typeof obj[i] == 'object') {
- $(obj[i]).data('fancybox', $.extend({}, opts, obj[i]));
- } else {
- obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts));
- }
- }
-
- selectedArray = jQuery.merge(selectedArray, obj);
-
- } else {
- if (typeof obj == 'object') {
- $(obj).data('fancybox', $.extend({}, opts, obj));
- } else {
- obj = $({}).data('fancybox', $.extend({content : obj}, opts));
- }
-
- selectedArray.push(obj);
- }
-
- if (selectedIndex > selectedArray.length || selectedIndex < 0) {
- selectedIndex = 0;
- }
-
- _start();
- };
-
- $.fancybox.showActivity = function() {
- clearInterval(loadingTimer);
-
- loading.show();
- loadingTimer = setInterval(_animate_loading, 66);
- };
-
- $.fancybox.hideActivity = function() {
- loading.hide();
- };
-
- $.fancybox.next = function() {
- return $.fancybox.pos( currentIndex + 1);
- };
-
- $.fancybox.prev = function() {
- return $.fancybox.pos( currentIndex - 1);
- };
-
- $.fancybox.pos = function(pos) {
- if (busy) {
- return;
- }
-
- pos = parseInt(pos);
-
- selectedArray = currentArray;
-
- if (pos > -1 && pos < currentArray.length) {
- selectedIndex = pos;
- _start();
-
- } else if (currentOpts.cyclic && currentArray.length > 1) {
- selectedIndex = pos >= currentArray.length ? 0 : currentArray.length - 1;
- _start();
- }
- };
-
- $.fancybox.cancel = function() {
- if (busy) {
- return;
- }
-
- busy = true;
-
- $.event.trigger('fancybox-cancel');
-
- _abort();
-
- selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts);
-
- busy = false;
- };
-
- // Note: within an iframe use - parent.$.fancybox.close();
- $.fancybox.close = function() {
- if (busy || wrap.is(':hidden')) {
- return;
- }
-
- busy = true;
-
- if (currentOpts && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) {
- busy = false;
- return;
- }
-
- _abort();
-
- $(close.add( nav_left ).add( nav_right )).hide();
-
- $(content.add( overlay )).unbind();
-
- $(window).unbind("resize.fb scroll.fb");
- $(document).unbind('keydown.fb');
-
- content.find('iframe').attr('src', isIE6 && /^https/i.test(window.location.href || '') ? 'javascript:void(false)' : 'about:blank');
-
- if (currentOpts.titlePosition !== 'inside') {
- title.empty();
- }
-
- wrap.stop();
-
- function _cleanup() {
- overlay.fadeOut('fast');
-
- title.empty().hide();
- wrap.hide();
-
- $.event.trigger('fancybox-cleanup');
-
- content.empty();
-
- currentOpts.onClosed(currentArray, currentIndex, currentOpts);
-
- currentArray = selectedOpts = [];
- currentIndex = selectedIndex = 0;
- currentOpts = selectedOpts = {};
-
- busy = false;
- }
-
- if (currentOpts.transitionOut == 'elastic') {
- start_pos = _get_zoom_from();
-
- var pos = wrap.position();
-
- final_pos = {
- top : pos.top ,
- left : pos.left,
- width : wrap.width(),
- height : wrap.height()
- };
-
- if (currentOpts.opacity) {
- final_pos.opacity = 1;
- }
-
- title.empty().hide();
-
- fx.prop = 1;
-
- $(fx).animate({ prop: 0 }, {
- duration : currentOpts.speedOut,
- easing : currentOpts.easingOut,
- step : _draw,
- complete : _cleanup
- });
-
- } else {
- wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup);
- }
- };
-
- $.fancybox.resize = function() {
- if (overlay.is(':visible')) {
- overlay.css('height', $(document).height());
- }
-
- $.fancybox.center(true);
- };
-
- $.fancybox.center = function() {
- var view, align;
-
- if (busy) {
- return;
- }
-
- align = arguments[0] === true ? 1 : 0;
- view = _get_viewport();
-
- if (!align && (wrap.width() > view[0] || wrap.height() > view[1])) {
- return;
- }
-
- wrap
- .stop()
- .animate({
- 'top' : parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - content.height() - 40) * 0.5) - currentOpts.padding)),
- 'left' : parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - content.width() - 40) * 0.5) - currentOpts.padding))
- }, typeof arguments[0] == 'number' ? arguments[0] : 200);
- };
-
- $.fancybox.init = function() {
- if ($("#fancybox-wrap").length) {
- return;
- }
-
- $('body').append(
- tmp = $('<div id="fancybox-tmp"></div>'),
- loading = $('<div id="fancybox-loading"><div></div></div>'),
- overlay = $('<div id="fancybox-overlay"></div>'),
- wrap = $('<div id="fancybox-wrap"></div>')
- );
-
- outer = $('<div id="fancybox-outer"></div>')
- .append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>')
- .appendTo( wrap );
-
- outer.append(
- content = $('<div id="fancybox-content"></div>'),
- close = $('<a id="fancybox-close"></a>'),
- title = $('<div id="fancybox-title"></div>'),
-
- nav_left = $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),
- nav_right = $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>')
- );
-
- close.click($.fancybox.close);
- loading.click($.fancybox.cancel);
-
- nav_left.click(function(e) {
- e.preventDefault();
- $.fancybox.prev();
- });
-
- nav_right.click(function(e) {
- e.preventDefault();
- $.fancybox.next();
- });
-
- if ($.fn.mousewheel) {
- wrap.bind('mousewheel.fb', function(e, delta) {
- if (busy) {
- e.preventDefault();
-
- } else if ($(e.target).get(0).clientHeight === 0 || $(e.target).get(0).scrollHeight === $(e.target).get(0).clientHeight) {
- e.preventDefault();
- $.fancybox[ delta > 0 ? 'prev' : 'next']();
- }
- });
- }
-
- if (!$.support.opacity) {
- wrap.addClass('fancybox-ie');
- }
-
- if (isIE6) {
- loading.addClass('fancybox-ie6');
- wrap.addClass('fancybox-ie6');
-
- $('<iframe id="fancybox-hide-sel-frame" src="' + (/^https/i.test(window.location.href || '') ? 'javascript:void(false)' : 'about:blank' ) + '" scrolling="no" border="0" frameborder="0" tabindex="-1"></iframe>').prependTo(outer);
- }
- };
-
- $.fn.fancybox.defaults = {
- padding : 10,
- margin : 40,
- opacity : false,
- modal : false,
- cyclic : false,
- scrolling : 'auto', // 'auto', 'yes' or 'no'
-
- width : 560,
- height : 340,
-
- autoScale : true,
- autoDimensions : true,
- centerOnScroll : false,
-
- ajax : {},
- swf : { wmode: 'transparent' },
-
- hideOnOverlayClick : true,
- hideOnContentClick : false,
-
- overlayShow : true,
- overlayOpacity : 0.7,
- overlayColor : '#777',
-
- titleShow : true,
- titlePosition : 'float', // 'float', 'outside', 'inside' or 'over'
- titleFormat : null,
- titleFromAlt : false,
-
- transitionIn : 'fade', // 'elastic', 'fade' or 'none'
- transitionOut : 'fade', // 'elastic', 'fade' or 'none'
-
- speedIn : 300,
- speedOut : 300,
-
- changeSpeed : 300,
- changeFade : 'fast',
-
- easingIn : 'swing',
- easingOut : 'swing',
-
- showCloseButton : true,
- showNavArrows : true,
- enableEscapeButton : true,
- enableKeyboardNav : true,
-
- onStart : function(){},
- onCancel : function(){},
- onComplete : function(){},
- onCleanup : function(){},
- onClosed : function(){},
- onError : function(){}
- };
-
- $(document).ready(function() {
- $.fancybox.init();
- });
-
-})(jQuery);
diff --git a/SemanticForms/libs/select2.js b/SemanticForms/libs/select2.js
deleted file mode 100644
index fdd18a71..00000000
--- a/SemanticForms/libs/select2.js
+++ /dev/null
@@ -1,3378 +0,0 @@
-/*
-Copyright 2012 Igor Vaynberg
-
-Version: @@ver@@ Timestamp: @@timestamp@@
-
-This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
-General Public License version 2 (the "GPL License"). You may choose either license to govern your
-use of this software only upon the condition that you accept all of the terms of either the Apache
-License or the GPL License.
-
-You may obtain a copy of the Apache License and the GPL License at:
-
- http://www.apache.org/licenses/LICENSE-2.0
- http://www.gnu.org/licenses/gpl-2.0.html
-
-Unless required by applicable law or agreed to in writing, software distributed under the
-Apache License or the GPL License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-CONDITIONS OF ANY KIND, either express or implied. See the Apache License and the GPL License for
-the specific language governing permissions and limitations under the Apache License and the GPL License.
-*/
-(function ($) {
- if(typeof $.fn.each2 == "undefined") {
- $.extend($.fn, {
- /*
- * 4-10 times faster .each replacement
- * use it carefully, as it overrides jQuery context of element on each iteration
- */
- each2 : function (c) {
- var j = $([0]), i = -1, l = this.length;
- while (
- ++i < l
- && (j.context = j[0] = this[i])
- && c.call(j[0], i, j) !== false //"this"=DOM, i=index, j=jQuery object
- );
- return this;
- }
- });
- }
-})(jQuery);
-
-(function ($, undefined) {
- "use strict";
- /*global document, window, jQuery, console */
-
- if (window.Select2 !== undefined) {
- return;
- }
-
- var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer,
- lastMousePosition={x:0,y:0}, $document, scrollBarDimensions,
-
- KEY = {
- TAB: 9,
- ENTER: 13,
- ESC: 27,
- SPACE: 32,
- LEFT: 37,
- UP: 38,
- RIGHT: 39,
- DOWN: 40,
- SHIFT: 16,
- CTRL: 17,
- ALT: 18,
- PAGE_UP: 33,
- PAGE_DOWN: 34,
- HOME: 36,
- END: 35,
- BACKSPACE: 8,
- DELETE: 46,
- isArrow: function (k) {
- k = k.which ? k.which : k;
- switch (k) {
- case KEY.LEFT:
- case KEY.RIGHT:
- case KEY.UP:
- case KEY.DOWN:
- return true;
- }
- return false;
- },
- isControl: function (e) {
- var k = e.which;
- switch (k) {
- case KEY.SHIFT:
- case KEY.CTRL:
- case KEY.ALT:
- return true;
- }
-
- if (e.metaKey) return true;
-
- return false;
- },
- isFunctionKey: function (k) {
- k = k.which ? k.which : k;
- return k >= 112 && k <= 123;
- }
- },
- MEASURE_SCROLLBAR_TEMPLATE = "<div class='select2-measure-scrollbar'></div>",
-
- DIACRITICS = {"\u24B6":"A","\uFF21":"A","\u00C0":"A","\u00C1":"A","\u00C2":"A","\u1EA6":"A","\u1EA4":"A","\u1EAA":"A","\u1EA8":"A","\u00C3":"A","\u0100":"A","\u0102":"A","\u1EB0":"A","\u1EAE":"A","\u1EB4":"A","\u1EB2":"A","\u0226":"A","\u01E0":"A","\u00C4":"A","\u01DE":"A","\u1EA2":"A","\u00C5":"A","\u01FA":"A","\u01CD":"A","\u0200":"A","\u0202":"A","\u1EA0":"A","\u1EAC":"A","\u1EB6":"A","\u1E00":"A","\u0104":"A","\u023A":"A","\u2C6F":"A","\uA732":"AA","\u00C6":"AE","\u01FC":"AE","\u01E2":"AE","\uA734":"AO","\uA736":"AU","\uA738":"AV","\uA73A":"AV","\uA73C":"AY","\u24B7":"B","\uFF22":"B","\u1E02":"B","\u1E04":"B","\u1E06":"B","\u0243":"B","\u0182":"B","\u0181":"B","\u24B8":"C","\uFF23":"C","\u0106":"C","\u0108":"C","\u010A":"C","\u010C":"C","\u00C7":"C","\u1E08":"C","\u0187":"C","\u023B":"C","\uA73E":"C","\u24B9":"D","\uFF24":"D","\u1E0A":"D","\u010E":"D","\u1E0C":"D","\u1E10":"D","\u1E12":"D","\u1E0E":"D","\u0110":"D","\u018B":"D","\u018A":"D","\u0189":"D","\uA779":"D","\u01F1":"DZ","\u01C4":"DZ","\u01F2":"Dz","\u01C5":"Dz","\u24BA":"E","\uFF25":"E","\u00C8":"E","\u00C9":"E","\u00CA":"E","\u1EC0":"E","\u1EBE":"E","\u1EC4":"E","\u1EC2":"E","\u1EBC":"E","\u0112":"E","\u1E14":"E","\u1E16":"E","\u0114":"E","\u0116":"E","\u00CB":"E","\u1EBA":"E","\u011A":"E","\u0204":"E","\u0206":"E","\u1EB8":"E","\u1EC6":"E","\u0228":"E","\u1E1C":"E","\u0118":"E","\u1E18":"E","\u1E1A":"E","\u0190":"E","\u018E":"E","\u24BB":"F","\uFF26":"F","\u1E1E":"F","\u0191":"F","\uA77B":"F","\u24BC":"G","\uFF27":"G","\u01F4":"G","\u011C":"G","\u1E20":"G","\u011E":"G","\u0120":"G","\u01E6":"G","\u0122":"G","\u01E4":"G","\u0193":"G","\uA7A0":"G","\uA77D":"G","\uA77E":"G","\u24BD":"H","\uFF28":"H","\u0124":"H","\u1E22":"H","\u1E26":"H","\u021E":"H","\u1E24":"H","\u1E28":"H","\u1E2A":"H","\u0126":"H","\u2C67":"H","\u2C75":"H","\uA78D":"H","\u24BE":"I","\uFF29":"I","\u00CC":"I","\u00CD":"I","\u00CE":"I","\u0128":"I","\u012A":"I","\u012C":"I","\u0130":"I","\u00CF":"I","\u1E2E":"I","\u1EC8":"I","\u01CF":"I","\u0208":"I","\u020A":"I","\u1ECA":"I","\u012E":"I","\u1E2C":"I","\u0197":"I","\u24BF":"J","\uFF2A":"J","\u0134":"J","\u0248":"J","\u24C0":"K","\uFF2B":"K","\u1E30":"K","\u01E8":"K","\u1E32":"K","\u0136":"K","\u1E34":"K","\u0198":"K","\u2C69":"K","\uA740":"K","\uA742":"K","\uA744":"K","\uA7A2":"K","\u24C1":"L","\uFF2C":"L","\u013F":"L","\u0139":"L","\u013D":"L","\u1E36":"L","\u1E38":"L","\u013B":"L","\u1E3C":"L","\u1E3A":"L","\u0141":"L","\u023D":"L","\u2C62":"L","\u2C60":"L","\uA748":"L","\uA746":"L","\uA780":"L","\u01C7":"LJ","\u01C8":"Lj","\u24C2":"M","\uFF2D":"M","\u1E3E":"M","\u1E40":"M","\u1E42":"M","\u2C6E":"M","\u019C":"M","\u24C3":"N","\uFF2E":"N","\u01F8":"N","\u0143":"N","\u00D1":"N","\u1E44":"N","\u0147":"N","\u1E46":"N","\u0145":"N","\u1E4A":"N","\u1E48":"N","\u0220":"N","\u019D":"N","\uA790":"N","\uA7A4":"N","\u01CA":"NJ","\u01CB":"Nj","\u24C4":"O","\uFF2F":"O","\u00D2":"O","\u00D3":"O","\u00D4":"O","\u1ED2":"O","\u1ED0":"O","\u1ED6":"O","\u1ED4":"O","\u00D5":"O","\u1E4C":"O","\u022C":"O","\u1E4E":"O","\u014C":"O","\u1E50":"O","\u1E52":"O","\u014E":"O","\u022E":"O","\u0230":"O","\u00D6":"O","\u022A":"O","\u1ECE":"O","\u0150":"O","\u01D1":"O","\u020C":"O","\u020E":"O","\u01A0":"O","\u1EDC":"O","\u1EDA":"O","\u1EE0":"O","\u1EDE":"O","\u1EE2":"O","\u1ECC":"O","\u1ED8":"O","\u01EA":"O","\u01EC":"O","\u00D8":"O","\u01FE":"O","\u0186":"O","\u019F":"O","\uA74A":"O","\uA74C":"O","\u01A2":"OI","\uA74E":"OO","\u0222":"OU","\u24C5":"P","\uFF30":"P","\u1E54":"P","\u1E56":"P","\u01A4":"P","\u2C63":"P","\uA750":"P","\uA752":"P","\uA754":"P","\u24C6":"Q","\uFF31":"Q","\uA756":"Q","\uA758":"Q","\u024A":"Q","\u24C7":"R","\uFF32":"R","\u0154":"R","\u1E58":"R","\u0158":"R","\u0210":"R","\u0212":"R","\u1E5A":"R","\u1E5C":"R","\u0156":"R","\u1E5E":"R","\u024C":"R","\u2C64":"R","\uA75A":"R","\uA7A6":"R","\uA782":"R","\u24C8":"S","\uFF33":"S","\u1E9E":"S","\u015A":"S","\u1E64":"S","\u015C":"S","\u1E60":"S","\u0160":"S","\u1E66":"S","\u1E62":"S","\u1E68":"S","\u0218":"S","\u015E":"S","\u2C7E":"S","\uA7A8":"S","\uA784":"S","\u24C9":"T","\uFF34":"T","\u1E6A":"T","\u0164":"T","\u1E6C":"T","\u021A":"T","\u0162":"T","\u1E70":"T","\u1E6E":"T","\u0166":"T","\u01AC":"T","\u01AE":"T","\u023E":"T","\uA786":"T","\uA728":"TZ","\u24CA":"U","\uFF35":"U","\u00D9":"U","\u00DA":"U","\u00DB":"U","\u0168":"U","\u1E78":"U","\u016A":"U","\u1E7A":"U","\u016C":"U","\u00DC":"U","\u01DB":"U","\u01D7":"U","\u01D5":"U","\u01D9":"U","\u1EE6":"U","\u016E":"U","\u0170":"U","\u01D3":"U","\u0214":"U","\u0216":"U","\u01AF":"U","\u1EEA":"U","\u1EE8":"U","\u1EEE":"U","\u1EEC":"U","\u1EF0":"U","\u1EE4":"U","\u1E72":"U","\u0172":"U","\u1E76":"U","\u1E74":"U","\u0244":"U","\u24CB":"V","\uFF36":"V","\u1E7C":"V","\u1E7E":"V","\u01B2":"V","\uA75E":"V","\u0245":"V","\uA760":"VY","\u24CC":"W","\uFF37":"W","\u1E80":"W","\u1E82":"W","\u0174":"W","\u1E86":"W","\u1E84":"W","\u1E88":"W","\u2C72":"W","\u24CD":"X","\uFF38":"X","\u1E8A":"X","\u1E8C":"X","\u24CE":"Y","\uFF39":"Y","\u1EF2":"Y","\u00DD":"Y","\u0176":"Y","\u1EF8":"Y","\u0232":"Y","\u1E8E":"Y","\u0178":"Y","\u1EF6":"Y","\u1EF4":"Y","\u01B3":"Y","\u024E":"Y","\u1EFE":"Y","\u24CF":"Z","\uFF3A":"Z","\u0179":"Z","\u1E90":"Z","\u017B":"Z","\u017D":"Z","\u1E92":"Z","\u1E94":"Z","\u01B5":"Z","\u0224":"Z","\u2C7F":"Z","\u2C6B":"Z","\uA762":"Z","\u24D0":"a","\uFF41":"a","\u1E9A":"a","\u00E0":"a","\u00E1":"a","\u00E2":"a","\u1EA7":"a","\u1EA5":"a","\u1EAB":"a","\u1EA9":"a","\u00E3":"a","\u0101":"a","\u0103":"a","\u1EB1":"a","\u1EAF":"a","\u1EB5":"a","\u1EB3":"a","\u0227":"a","\u01E1":"a","\u00E4":"a","\u01DF":"a","\u1EA3":"a","\u00E5":"a","\u01FB":"a","\u01CE":"a","\u0201":"a","\u0203":"a","\u1EA1":"a","\u1EAD":"a","\u1EB7":"a","\u1E01":"a","\u0105":"a","\u2C65":"a","\u0250":"a","\uA733":"aa","\u00E6":"ae","\u01FD":"ae","\u01E3":"ae","\uA735":"ao","\uA737":"au","\uA739":"av","\uA73B":"av","\uA73D":"ay","\u24D1":"b","\uFF42":"b","\u1E03":"b","\u1E05":"b","\u1E07":"b","\u0180":"b","\u0183":"b","\u0253":"b","\u24D2":"c","\uFF43":"c","\u0107":"c","\u0109":"c","\u010B":"c","\u010D":"c","\u00E7":"c","\u1E09":"c","\u0188":"c","\u023C":"c","\uA73F":"c","\u2184":"c","\u24D3":"d","\uFF44":"d","\u1E0B":"d","\u010F":"d","\u1E0D":"d","\u1E11":"d","\u1E13":"d","\u1E0F":"d","\u0111":"d","\u018C":"d","\u0256":"d","\u0257":"d","\uA77A":"d","\u01F3":"dz","\u01C6":"dz","\u24D4":"e","\uFF45":"e","\u00E8":"e","\u00E9":"e","\u00EA":"e","\u1EC1":"e","\u1EBF":"e","\u1EC5":"e","\u1EC3":"e","\u1EBD":"e","\u0113":"e","\u1E15":"e","\u1E17":"e","\u0115":"e","\u0117":"e","\u00EB":"e","\u1EBB":"e","\u011B":"e","\u0205":"e","\u0207":"e","\u1EB9":"e","\u1EC7":"e","\u0229":"e","\u1E1D":"e","\u0119":"e","\u1E19":"e","\u1E1B":"e","\u0247":"e","\u025B":"e","\u01DD":"e","\u24D5":"f","\uFF46":"f","\u1E1F":"f","\u0192":"f","\uA77C":"f","\u24D6":"g","\uFF47":"g","\u01F5":"g","\u011D":"g","\u1E21":"g","\u011F":"g","\u0121":"g","\u01E7":"g","\u0123":"g","\u01E5":"g","\u0260":"g","\uA7A1":"g","\u1D79":"g","\uA77F":"g","\u24D7":"h","\uFF48":"h","\u0125":"h","\u1E23":"h","\u1E27":"h","\u021F":"h","\u1E25":"h","\u1E29":"h","\u1E2B":"h","\u1E96":"h","\u0127":"h","\u2C68":"h","\u2C76":"h","\u0265":"h","\u0195":"hv","\u24D8":"i","\uFF49":"i","\u00EC":"i","\u00ED":"i","\u00EE":"i","\u0129":"i","\u012B":"i","\u012D":"i","\u00EF":"i","\u1E2F":"i","\u1EC9":"i","\u01D0":"i","\u0209":"i","\u020B":"i","\u1ECB":"i","\u012F":"i","\u1E2D":"i","\u0268":"i","\u0131":"i","\u24D9":"j","\uFF4A":"j","\u0135":"j","\u01F0":"j","\u0249":"j","\u24DA":"k","\uFF4B":"k","\u1E31":"k","\u01E9":"k","\u1E33":"k","\u0137":"k","\u1E35":"k","\u0199":"k","\u2C6A":"k","\uA741":"k","\uA743":"k","\uA745":"k","\uA7A3":"k","\u24DB":"l","\uFF4C":"l","\u0140":"l","\u013A":"l","\u013E":"l","\u1E37":"l","\u1E39":"l","\u013C":"l","\u1E3D":"l","\u1E3B":"l","\u017F":"l","\u0142":"l","\u019A":"l","\u026B":"l","\u2C61":"l","\uA749":"l","\uA781":"l","\uA747":"l","\u01C9":"lj","\u24DC":"m","\uFF4D":"m","\u1E3F":"m","\u1E41":"m","\u1E43":"m","\u0271":"m","\u026F":"m","\u24DD":"n","\uFF4E":"n","\u01F9":"n","\u0144":"n","\u00F1":"n","\u1E45":"n","\u0148":"n","\u1E47":"n","\u0146":"n","\u1E4B":"n","\u1E49":"n","\u019E":"n","\u0272":"n","\u0149":"n","\uA791":"n","\uA7A5":"n","\u01CC":"nj","\u24DE":"o","\uFF4F":"o","\u00F2":"o","\u00F3":"o","\u00F4":"o","\u1ED3":"o","\u1ED1":"o","\u1ED7":"o","\u1ED5":"o","\u00F5":"o","\u1E4D":"o","\u022D":"o","\u1E4F":"o","\u014D":"o","\u1E51":"o","\u1E53":"o","\u014F":"o","\u022F":"o","\u0231":"o","\u00F6":"o","\u022B":"o","\u1ECF":"o","\u0151":"o","\u01D2":"o","\u020D":"o","\u020F":"o","\u01A1":"o","\u1EDD":"o","\u1EDB":"o","\u1EE1":"o","\u1EDF":"o","\u1EE3":"o","\u1ECD":"o","\u1ED9":"o","\u01EB":"o","\u01ED":"o","\u00F8":"o","\u01FF":"o","\u0254":"o","\uA74B":"o","\uA74D":"o","\u0275":"o","\u01A3":"oi","\u0223":"ou","\uA74F":"oo","\u24DF":"p","\uFF50":"p","\u1E55":"p","\u1E57":"p","\u01A5":"p","\u1D7D":"p","\uA751":"p","\uA753":"p","\uA755":"p","\u24E0":"q","\uFF51":"q","\u024B":"q","\uA757":"q","\uA759":"q","\u24E1":"r","\uFF52":"r","\u0155":"r","\u1E59":"r","\u0159":"r","\u0211":"r","\u0213":"r","\u1E5B":"r","\u1E5D":"r","\u0157":"r","\u1E5F":"r","\u024D":"r","\u027D":"r","\uA75B":"r","\uA7A7":"r","\uA783":"r","\u24E2":"s","\uFF53":"s","\u00DF":"s","\u015B":"s","\u1E65":"s","\u015D":"s","\u1E61":"s","\u0161":"s","\u1E67":"s","\u1E63":"s","\u1E69":"s","\u0219":"s","\u015F":"s","\u023F":"s","\uA7A9":"s","\uA785":"s","\u1E9B":"s","\u24E3":"t","\uFF54":"t","\u1E6B":"t","\u1E97":"t","\u0165":"t","\u1E6D":"t","\u021B":"t","\u0163":"t","\u1E71":"t","\u1E6F":"t","\u0167":"t","\u01AD":"t","\u0288":"t","\u2C66":"t","\uA787":"t","\uA729":"tz","\u24E4":"u","\uFF55":"u","\u00F9":"u","\u00FA":"u","\u00FB":"u","\u0169":"u","\u1E79":"u","\u016B":"u","\u1E7B":"u","\u016D":"u","\u00FC":"u","\u01DC":"u","\u01D8":"u","\u01D6":"u","\u01DA":"u","\u1EE7":"u","\u016F":"u","\u0171":"u","\u01D4":"u","\u0215":"u","\u0217":"u","\u01B0":"u","\u1EEB":"u","\u1EE9":"u","\u1EEF":"u","\u1EED":"u","\u1EF1":"u","\u1EE5":"u","\u1E73":"u","\u0173":"u","\u1E77":"u","\u1E75":"u","\u0289":"u","\u24E5":"v","\uFF56":"v","\u1E7D":"v","\u1E7F":"v","\u028B":"v","\uA75F":"v","\u028C":"v","\uA761":"vy","\u24E6":"w","\uFF57":"w","\u1E81":"w","\u1E83":"w","\u0175":"w","\u1E87":"w","\u1E85":"w","\u1E98":"w","\u1E89":"w","\u2C73":"w","\u24E7":"x","\uFF58":"x","\u1E8B":"x","\u1E8D":"x","\u24E8":"y","\uFF59":"y","\u1EF3":"y","\u00FD":"y","\u0177":"y","\u1EF9":"y","\u0233":"y","\u1E8F":"y","\u00FF":"y","\u1EF7":"y","\u1E99":"y","\u1EF5":"y","\u01B4":"y","\u024F":"y","\u1EFF":"y","\u24E9":"z","\uFF5A":"z","\u017A":"z","\u1E91":"z","\u017C":"z","\u017E":"z","\u1E93":"z","\u1E95":"z","\u01B6":"z","\u0225":"z","\u0240":"z","\u2C6C":"z","\uA763":"z"};
-
- $document = $(document);
-
- nextUid=(function() { var counter=1; return function() { return counter++; }; }());
-
-
- function reinsertElement(element) {
- var placeholder = $(document.createTextNode(''));
-
- element.before(placeholder);
- placeholder.before(element);
- placeholder.remove();
- }
-
- function stripDiacritics(str) {
- var ret, i, l, c;
-
- if (!str || str.length < 1) return str;
-
- ret = "";
- for (i = 0, l = str.length; i < l; i++) {
- c = str.charAt(i);
- ret += DIACRITICS[c] || c;
- }
- return ret;
- }
-
- function indexOf(value, array) {
- var i = 0, l = array.length;
- for (; i < l; i = i + 1) {
- if (equal(value, array[i])) return i;
- }
- return -1;
- }
-
- function measureScrollbar () {
- var $template = $( MEASURE_SCROLLBAR_TEMPLATE );
- $template.appendTo('body');
-
- var dim = {
- width: $template.width() - $template[0].clientWidth,
- height: $template.height() - $template[0].clientHeight
- };
- $template.remove();
-
- return dim;
- }
-
- /**
- * Compares equality of a and b
- * @param a
- * @param b
- */
- function equal(a, b) {
- if (a === b) return true;
- if (a === undefined || b === undefined) return false;
- if (a === null || b === null) return false;
- // Check whether 'a' or 'b' is a string (primitive or object).
- // The concatenation of an empty string (+'') converts its argument to a string's primitive.
- if (a.constructor === String) return a+'' === b+''; // a+'' - in case 'a' is a String object
- if (b.constructor === String) return b+'' === a+''; // b+'' - in case 'b' is a String object
- return false;
- }
-
- /**
- * Splits the string into an array of values, trimming each value. An empty array is returned for nulls or empty
- * strings
- * @param string
- * @param separator
- */
- function splitVal(string, separator) {
- var val, i, l;
- if (string === null || string.length < 1) return [];
- val = string.split(separator);
- for (i = 0, l = val.length; i < l; i = i + 1) val[i] = $.trim(val[i]);
- return val;
- }
-
- function getSideBorderPadding(element) {
- return element.outerWidth(false) - element.width();
- }
-
- function installKeyUpChangeEvent(element) {
- var key="keyup-change-value";
- element.on("keydown", function () {
- if ($.data(element, key) === undefined) {
- $.data(element, key, element.val());
- }
- });
- element.on("keyup", function () {
- var val= $.data(element, key);
- if (val !== undefined && element.val() !== val) {
- $.removeData(element, key);
- element.trigger("keyup-change");
- }
- });
- }
-
- $document.on("mousemove", function (e) {
- lastMousePosition.x = e.pageX;
- lastMousePosition.y = e.pageY;
- });
-
- /**
- * filters mouse events so an event is fired only if the mouse moved.
- *
- * filters out mouse events that occur when mouse is stationary but
- * the elements under the pointer are scrolled.
- */
- function installFilteredMouseMove(element) {
- element.on("mousemove", function (e) {
- var lastpos = lastMousePosition;
- if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) {
- $(e.target).trigger("mousemove-filtered", e);
- }
- });
- }
-
- /**
- * Debounces a function. Returns a function that calls the original fn function only if no invocations have been made
- * within the last quietMillis milliseconds.
- *
- * @param quietMillis number of milliseconds to wait before invoking fn
- * @param fn function to be debounced
- * @param ctx object to be used as this reference within fn
- * @return debounced version of fn
- */
- function debounce(quietMillis, fn, ctx) {
- ctx = ctx || undefined;
- var timeout;
- return function () {
- var args = arguments;
- window.clearTimeout(timeout);
- timeout = window.setTimeout(function() {
- fn.apply(ctx, args);
- }, quietMillis);
- };
- }
-
- /**
- * A simple implementation of a thunk
- * @param formula function used to lazily initialize the thunk
- * @return {Function}
- */
- function thunk(formula) {
- var evaluated = false,
- value;
- return function() {
- if (evaluated === false) { value = formula(); evaluated = true; }
- return value;
- };
- };
-
- function installDebouncedScroll(threshold, element) {
- var notify = debounce(threshold, function (e) { element.trigger("scroll-debounced", e);});
- element.on("scroll", function (e) {
- if (indexOf(e.target, element.get()) >= 0) notify(e);
- });
- }
-
- function focus($el) {
- if ($el[0] === document.activeElement) return;
-
- /* set the focus in a 0 timeout - that way the focus is set after the processing
- of the current event has finished - which seems like the only reliable way
- to set focus */
- window.setTimeout(function() {
- var el=$el[0], pos=$el.val().length, range;
-
- $el.focus();
-
- /* make sure el received focus so we do not error out when trying to manipulate the caret.
- sometimes modals or others listeners may steal it after its set */
- var isVisible = (el.offsetWidth > 0 || el.offsetHeight > 0);
- if (isVisible && el === document.activeElement) {
-
- /* after the focus is set move the caret to the end, necessary when we val()
- just before setting focus */
- if(el.setSelectionRange)
- {
- el.setSelectionRange(pos, pos);
- }
- else if (el.createTextRange) {
- range = el.createTextRange();
- range.collapse(false);
- range.select();
- }
- }
- }, 0);
- }
-
- function getCursorInfo(el) {
- el = $(el)[0];
- var offset = 0;
- var length = 0;
- if ('selectionStart' in el) {
- offset = el.selectionStart;
- length = el.selectionEnd - offset;
- } else if ('selection' in document) {
- el.focus();
- var sel = document.selection.createRange();
- length = document.selection.createRange().text.length;
- sel.moveStart('character', -el.value.length);
- offset = sel.text.length - length;
- }
- return { offset: offset, length: length };
- }
-
- function killEvent(event) {
- event.preventDefault();
- event.stopPropagation();
- }
- function killEventImmediately(event) {
- event.preventDefault();
- event.stopImmediatePropagation();
- }
-
- function measureTextWidth(e) {
- if (!sizer){
- var style = e[0].currentStyle || window.getComputedStyle(e[0], null);
- sizer = $(document.createElement("div")).css({
- position: "absolute",
- left: "-10000px",
- top: "-10000px",
- display: "none",
- fontSize: style.fontSize,
- fontFamily: style.fontFamily,
- fontStyle: style.fontStyle,
- fontWeight: style.fontWeight,
- letterSpacing: style.letterSpacing,
- textTransform: style.textTransform,
- whiteSpace: "nowrap"
- });
- sizer.attr("class","select2-sizer");
- $("body").append(sizer);
- }
- sizer.text(e.val());
- return sizer.width();
- }
-
- function syncCssClasses(dest, src, adapter) {
- var classes, replacements = [], adapted;
-
- classes = dest.attr("class");
- if (classes) {
- classes = '' + classes; // for IE which returns object
- $(classes.split(" ")).each2(function() {
- if (this.indexOf("select2-") === 0) {
- replacements.push(this);
- }
- });
- }
- classes = src.attr("class");
- if (classes) {
- classes = '' + classes; // for IE which returns object
- $(classes.split(" ")).each2(function() {
- if (this.indexOf("select2-") !== 0) {
- adapted = adapter(this);
- if (adapted) {
- replacements.push(adapted);
- }
- }
- });
- }
- dest.attr("class", replacements.join(" "));
- }
-
-
- function markMatch(text, term, markup, escapeMarkup) {
- var match=stripDiacritics(text.toUpperCase()).indexOf(stripDiacritics(term.toUpperCase())),
- tl=term.length;
-
- if (match<0) {
- markup.push(escapeMarkup(text));
- return;
- }
-
- markup.push(escapeMarkup(text.substring(0, match)));
- markup.push("<span class='select2-match'>");
- markup.push(escapeMarkup(text.substring(match, match + tl)));
- markup.push("</span>");
- markup.push(escapeMarkup(text.substring(match + tl, text.length)));
- }
-
- function defaultEscapeMarkup(markup) {
- var replace_map = {
- '\\': '&#92;',
- '&': '&amp;',
- '<': '&lt;',
- '>': '&gt;',
- '"': '&quot;',
- "'": '&#39;',
- "/": '&#47;'
- };
-
- return String(markup).replace(/[&<>"'\/\\]/g, function (match) {
- return replace_map[match];
- });
- }
-
- /**
- * Produces an ajax-based query function
- *
- * @param options object containing configuration parameters
- * @param options.params parameter map for the transport ajax call, can contain such options as cache, jsonpCallback, etc. see $.ajax
- * @param options.transport function that will be used to execute the ajax request. must be compatible with parameters supported by $.ajax
- * @param options.url url for the data
- * @param options.data a function(searchTerm, pageNumber, context) that should return an object containing query string parameters for the above url.
- * @param options.dataType request data type: ajax, jsonp, other datatypes supported by jQuery's $.ajax function or the transport function if specified
- * @param options.quietMillis (optional) milliseconds to wait before making the ajaxRequest, helps debounce the ajax function if invoked too often
- * @param options.results a function(remoteData, pageNumber) that converts data returned form the remote request to the format expected by Select2.
- * The expected format is an object containing the following keys:
- * results array of objects that will be used as choices
- * more (optional) boolean indicating whether there are more results available
- * Example: {results:[{id:1, text:'Red'},{id:2, text:'Blue'}], more:true}
- */
- function ajax(options) {
- var timeout, // current scheduled but not yet executed request
- handler = null,
- quietMillis = options.quietMillis || 100,
- ajaxUrl = options.url,
- self = this;
-
- return function (query) {
- window.clearTimeout(timeout);
- timeout = window.setTimeout(function () {
- var data = options.data, // ajax data function
- url = ajaxUrl, // ajax url string or function
- transport = options.transport || $.fn.select2.ajaxDefaults.transport,
- // deprecated - to be removed in 4.0 - use params instead
- deprecated = {
- type: options.type || 'GET', // set type of request (GET or POST)
- cache: options.cache || false,
- jsonpCallback: options.jsonpCallback||undefined,
- dataType: options.dataType||"json"
- },
- params = $.extend({}, $.fn.select2.ajaxDefaults.params, deprecated);
-
- data = data ? data.call(self, query.term, query.page, query.context) : null;
- url = (typeof url === 'function') ? url.call(self, query.term, query.page, query.context) : url;
-
- if (handler && typeof handler.abort === "function") { handler.abort(); }
-
- if (options.params) {
- if ($.isFunction(options.params)) {
- $.extend(params, options.params.call(self));
- } else {
- $.extend(params, options.params);
- }
- }
-
- $.extend(params, {
- url: url,
- dataType: options.dataType,
- data: data,
- success: function (data) {
- // TODO - replace query.page with query so users have access to term, page, etc.
- var results = options.results(data, query.page);
- query.callback(results);
- }
- });
- handler = transport.call(self, params);
- }, quietMillis);
- };
- }
-
- /**
- * Produces a query function that works with a local array
- *
- * @param options object containing configuration parameters. The options parameter can either be an array or an
- * object.
- *
- * If the array form is used it is assumed that it contains objects with 'id' and 'text' keys.
- *
- * If the object form is used ti is assumed that it contains 'data' and 'text' keys. The 'data' key should contain
- * an array of objects that will be used as choices. These objects must contain at least an 'id' key. The 'text'
- * key can either be a String in which case it is expected that each element in the 'data' array has a key with the
- * value of 'text' which will be used to match choices. Alternatively, text can be a function(item) that can extract
- * the text.
- */
- function local(options) {
- var data = options, // data elements
- dataText,
- tmp,
- text = function (item) { return ""+item.text; }; // function used to retrieve the text portion of a data item that is matched against the search
-
- if ($.isArray(data)) {
- tmp = data;
- data = { results: tmp };
- }
-
- if ($.isFunction(data) === false) {
- tmp = data;
- data = function() { return tmp; };
- }
-
- var dataItem = data();
- if (dataItem.text) {
- text = dataItem.text;
- // if text is not a function we assume it to be a key name
- if (!$.isFunction(text)) {
- dataText = dataItem.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available
- text = function (item) { return item[dataText]; };
- }
- }
-
- return function (query) {
- var t = query.term, filtered = { results: [] }, process;
- if (t === "") {
- query.callback(data());
- return;
- }
-
- process = function(datum, collection) {
- var group, attr;
- datum = datum[0];
- if (datum.children) {
- group = {};
- for (attr in datum) {
- if (datum.hasOwnProperty(attr)) group[attr]=datum[attr];
- }
- group.children=[];
- $(datum.children).each2(function(i, childDatum) { process(childDatum, group.children); });
- if (group.children.length || query.matcher(t, text(group), datum)) {
- collection.push(group);
- }
- } else {
- if (query.matcher(t, text(datum), datum)) {
- collection.push(datum);
- }
- }
- };
-
- $(data().results).each2(function(i, datum) { process(datum, filtered.results); });
- query.callback(filtered);
- };
- }
-
- // TODO javadoc
- function tags(data) {
- var isFunc = $.isFunction(data);
- return function (query) {
- var t = query.term, filtered = {results: []};
- $(isFunc ? data() : data).each(function () {
- var isObject = this.text !== undefined,
- text = isObject ? this.text : this;
- if (t === "" || query.matcher(t, text)) {
- filtered.results.push(isObject ? this : {id: this, text: this});
- }
- });
- query.callback(filtered);
- };
- }
-
- /**
- * Checks if the formatter function should be used.
- *
- * Throws an error if it is not a function. Returns true if it should be used,
- * false if no formatting should be performed.
- *
- * @param formatter
- */
- function checkFormatter(formatter, formatterName) {
- if ($.isFunction(formatter)) return true;
- if (!formatter) return false;
- if (typeof(formatter) === 'string') return true;
- throw new Error(formatterName +" must be a string, function, or falsy value");
- }
-
- function evaluate(val) {
- if ($.isFunction(val)) {
- var args = Array.prototype.slice.call(arguments, 1);
- return val.apply(null, args);
- }
- return val;
- }
-
- function countResults(results) {
- var count = 0;
- $.each(results, function(i, item) {
- if (item.children) {
- count += countResults(item.children);
- } else {
- count++;
- }
- });
- return count;
- }
-
- /**
- * Default tokenizer. This function uses breaks the input on substring match of any string from the
- * opts.tokenSeparators array and uses opts.createSearchChoice to create the choice object. Both of those
- * two options have to be defined in order for the tokenizer to work.
- *
- * @param input text user has typed so far or pasted into the search field
- * @param selection currently selected choices
- * @param selectCallback function(choice) callback tho add the choice to selection
- * @param opts select2's opts
- * @return undefined/null to leave the current input unchanged, or a string to change the input to the returned value
- */
- function defaultTokenizer(input, selection, selectCallback, opts) {
- var original = input, // store the original so we can compare and know if we need to tell the search to update its text
- dupe = false, // check for whether a token we extracted represents a duplicate selected choice
- token, // token
- index, // position at which the separator was found
- i, l, // looping variables
- separator; // the matched separator
-
- if (!opts.createSearchChoice || !opts.tokenSeparators || opts.tokenSeparators.length < 1) return undefined;
-
- while (true) {
- index = -1;
-
- for (i = 0, l = opts.tokenSeparators.length; i < l; i++) {
- separator = opts.tokenSeparators[i];
- index = input.indexOf(separator);
- if (index >= 0) break;
- }
-
- if (index < 0) break; // did not find any token separator in the input string, bail
-
- token = input.substring(0, index);
- input = input.substring(index + separator.length);
-
- if (token.length > 0) {
- token = opts.createSearchChoice.call(this, token, selection);
- if (token !== undefined && token !== null && opts.id(token) !== undefined && opts.id(token) !== null) {
- dupe = false;
- for (i = 0, l = selection.length; i < l; i++) {
- if (equal(opts.id(token), opts.id(selection[i]))) {
- dupe = true; break;
- }
- }
-
- if (!dupe) selectCallback(token);
- }
- }
- }
-
- if (original!==input) return input;
- }
-
- /**
- * Creates a new class
- *
- * @param superClass
- * @param methods
- */
- function clazz(SuperClass, methods) {
- var constructor = function () {};
- constructor.prototype = new SuperClass;
- constructor.prototype.constructor = constructor;
- constructor.prototype.parent = SuperClass.prototype;
- constructor.prototype = $.extend(constructor.prototype, methods);
- return constructor;
- }
-
- AbstractSelect2 = clazz(Object, {
-
- // abstract
- bind: function (func) {
- var self = this;
- return function () {
- func.apply(self, arguments);
- };
- },
-
- // abstract
- init: function (opts) {
- var results, search, resultsSelector = ".select2-results";
-
- // prepare options
- this.opts = opts = this.prepareOpts(opts);
-
- this.id=opts.id;
-
- // destroy if called on an existing component
- if (opts.element.data("select2") !== undefined &&
- opts.element.data("select2") !== null) {
- opts.element.data("select2").destroy();
- }
-
- this.container = this.createContainer();
-
- this.liveRegion = $("<span>", {
- role: "status",
- "aria-live": "polite"
- })
- .addClass("select2-hidden-accessible")
- .appendTo(document.body);
-
- this.containerId="s2id_"+(opts.element.attr("id") || "autogen"+nextUid()).replace(/([;&,\-\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
- this.containerSelector="#"+this.containerId;
- this.container.attr("id", this.containerId);
-
- // cache the body so future lookups are cheap
- this.body = thunk(function() { return opts.element.closest("body"); });
-
- syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
-
- this.container.attr("style", opts.element.attr("style"));
- this.container.css(evaluate(opts.containerCss));
- this.container.addClass(evaluate(opts.containerCssClass));
-
- this.elementTabIndex = this.opts.element.attr("tabindex");
-
- // swap container for the element
- this.opts.element
- .data("select2", this)
- .attr("tabindex", "-1")
- .before(this.container)
- .on("click.select2", killEvent); // do not leak click events
-
- this.container.data("select2", this);
-
- this.dropdown = this.container.find(".select2-drop");
-
- syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);
-
- this.dropdown.addClass(evaluate(opts.dropdownCssClass));
- this.dropdown.data("select2", this);
- this.dropdown.on("click", killEvent);
-
- this.results = results = this.container.find(resultsSelector);
- this.search = search = this.container.find("input.select2-input");
-
- this.queryCount = 0;
- this.resultsPage = 0;
- this.context = null;
-
- // initialize the container
- this.initContainer();
-
- this.container.on("click", killEvent);
-
- installFilteredMouseMove(this.results);
- this.dropdown.on("mousemove-filtered touchstart touchmove touchend", resultsSelector, this.bind(this.highlightUnderEvent));
-
- installDebouncedScroll(80, this.results);
- this.dropdown.on("scroll-debounced", resultsSelector, this.bind(this.loadMoreIfNeeded));
-
- // do not propagate change event from the search field out of the component
- $(this.container).on("change", ".select2-input", function(e) {e.stopPropagation();});
- $(this.dropdown).on("change", ".select2-input", function(e) {e.stopPropagation();});
-
- // if jquery.mousewheel plugin is installed we can prevent out-of-bounds scrolling of results via mousewheel
- if ($.fn.mousewheel) {
- results.mousewheel(function (e, delta, deltaX, deltaY) {
- var top = results.scrollTop();
- if (deltaY > 0 && top - deltaY <= 0) {
- results.scrollTop(0);
- killEvent(e);
- } else if (deltaY < 0 && results.get(0).scrollHeight - results.scrollTop() + deltaY <= results.height()) {
- results.scrollTop(results.get(0).scrollHeight - results.height());
- killEvent(e);
- }
- });
- }
-
- installKeyUpChangeEvent(search);
- search.on("keyup-change input paste", this.bind(this.updateResults));
- search.on("focus", function () { search.addClass("select2-focused"); });
- search.on("blur", function () { search.removeClass("select2-focused");});
-
- this.dropdown.on("mouseup", resultsSelector, this.bind(function (e) {
- if ($(e.target).closest(".select2-result-selectable").length > 0) {
- this.highlightUnderEvent(e);
- this.selectHighlighted(e);
- }
- }));
-
- // trap all mouse events from leaving the dropdown. sometimes there may be a modal that is listening
- // for mouse events outside of itself so it can close itself. since the dropdown is now outside the select2's
- // dom it will trigger the popup close, which is not what we want
- this.dropdown.on("click mouseup mousedown", function (e) { e.stopPropagation(); });
-
- this.nextSearchTerm = undefined;
-
- if ($.isFunction(this.opts.initSelection)) {
- // initialize selection based on the current value of the source element
- this.initSelection();
-
- // if the user has provided a function that can set selection based on the value of the source element
- // we monitor the change event on the element and trigger it, allowing for two way synchronization
- this.monitorSource();
- }
-
- if (opts.maximumInputLength !== null) {
- this.search.attr("maxlength", opts.maximumInputLength);
- }
-
- var disabled = opts.element.prop("disabled");
- if (disabled === undefined) disabled = false;
- this.enable(!disabled);
-
- var readonly = opts.element.prop("readonly");
- if (readonly === undefined) readonly = false;
- this.readonly(readonly);
-
- // Calculate size of scrollbar
- scrollBarDimensions = scrollBarDimensions || measureScrollbar();
-
- this.autofocus = opts.element.prop("autofocus");
- opts.element.prop("autofocus", false);
- if (this.autofocus) this.focus();
-
- this.search.attr("placeholder", opts.searchInputPlaceholder);
- },
-
- // abstract
- destroy: function () {
- var element=this.opts.element, select2 = element.data("select2");
-
- this.close();
-
- if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; }
-
- if (select2 !== undefined) {
- select2.container.remove();
- select2.liveRegion.remove();
- select2.dropdown.remove();
- element
- .removeClass("select2-offscreen")
- .removeData("select2")
- .off(".select2")
- .prop("autofocus", this.autofocus || false);
- if (this.elementTabIndex) {
- element.attr({tabindex: this.elementTabIndex});
- } else {
- element.removeAttr("tabindex");
- }
- element.show();
- }
- },
-
- // abstract
- optionToData: function(element) {
- if (element.is("option")) {
- return {
- id:element.prop("value"),
- text:element.text(),
- element: element.get(),
- css: element.attr("class"),
- disabled: element.prop("disabled"),
- locked: equal(element.attr("locked"), "locked") || equal(element.data("locked"), true)
- };
- } else if (element.is("optgroup")) {
- return {
- text:element.attr("label"),
- children:[],
- element: element.get(),
- css: element.attr("class")
- };
- }
- },
-
- // abstract
- prepareOpts: function (opts) {
- var element, select, idKey, ajaxUrl, self = this;
-
- element = opts.element;
-
- if (element.get(0).tagName.toLowerCase() === "select") {
- this.select = select = opts.element;
- }
-
- if (select) {
- // these options are not allowed when attached to a select because they are picked up off the element itself
- $.each(["id", "multiple", "ajax", "query", "createSearchChoice", "initSelection", "data", "tags"], function () {
- if (this in opts) {
- throw new Error("Option '" + this + "' is not allowed for Select2 when attached to a <select> element.");
- }
- });
- }
-
- opts = $.extend({}, {
- populateResults: function(container, results, query) {
- var populate, id=this.opts.id, liveRegion=this.liveRegion;
-
- populate=function(results, container, depth) {
-
- var i, l, result, selectable, disabled, compound, node, label, innerContainer, formatted;
-
- results = opts.sortResults(results, container, query);
-
- for (i = 0, l = results.length; i < l; i = i + 1) {
-
- result=results[i];
-
- disabled = (result.disabled === true);
- selectable = (!disabled) && (id(result) !== undefined);
-
- compound=result.children && result.children.length > 0;
-
- node=$("<li></li>");
- node.addClass("select2-results-dept-"+depth);
- node.addClass("select2-result");
- node.addClass(selectable ? "select2-result-selectable" : "select2-result-unselectable");
- if (disabled) { node.addClass("select2-disabled"); }
- if (compound) { node.addClass("select2-result-with-children"); }
- node.addClass(self.opts.formatResultCssClass(result));
- node.attr("role", "presentation");
-
- label=$(document.createElement("div"));
- label.addClass("select2-result-label");
- label.attr("id", "select2-result-label-" + nextUid());
- label.attr("role", "option");
-
- formatted=opts.formatResult(result, label, query, self.opts.escapeMarkup);
- if (formatted!==undefined) {
- label.html(formatted);
- node.append(label);
- }
-
-
- if (compound) {
-
- innerContainer=$("<ul></ul>");
- innerContainer.addClass("select2-result-sub");
- populate(result.children, innerContainer, depth+1);
- node.append(innerContainer);
- }
-
- node.data("select2-data", result);
- container.append(node);
- }
-
- liveRegion.text(opts.formatMatches(results.length));
- };
-
- populate(results, container, 0);
- }
- }, $.fn.select2.defaults, opts);
-
- if (typeof(opts.id) !== "function") {
- idKey = opts.id;
- opts.id = function (e) { return e[idKey]; };
- }
-
- if ($.isArray(opts.element.data("select2Tags"))) {
- if ("tags" in opts) {
- throw "tags specified as both an attribute 'data-select2-tags' and in options of Select2 " + opts.element.attr("id");
- }
- opts.tags=opts.element.data("select2Tags");
- }
-
- if (select) {
- opts.query = this.bind(function (query) {
- var data = { results: [], more: false },
- term = query.term,
- children, placeholderOption, process;
-
- process=function(element, collection) {
- var group;
- if (element.is("option")) {
- if (query.matcher(term, element.text(), element)) {
- collection.push(self.optionToData(element));
- }
- } else if (element.is("optgroup")) {
- group=self.optionToData(element);
- element.children().each2(function(i, elm) { process(elm, group.children); });
- if (group.children.length>0) {
- collection.push(group);
- }
- }
- };
-
- children=element.children();
-
- // ignore the placeholder option if there is one
- if (this.getPlaceholder() !== undefined && children.length > 0) {
- placeholderOption = this.getPlaceholderOption();
- if (placeholderOption) {
- children=children.not(placeholderOption);
- }
- }
-
- children.each2(function(i, elm) { process(elm, data.results); });
-
- query.callback(data);
- });
- // this is needed because inside val() we construct choices from options and there id is hardcoded
- opts.id=function(e) { return e.id; };
- } else {
- if (!("query" in opts)) {
-
- if ("ajax" in opts) {
- ajaxUrl = opts.element.data("ajax-url");
- if (ajaxUrl && ajaxUrl.length > 0) {
- opts.ajax.url = ajaxUrl;
- }
- opts.query = ajax.call(opts.element, opts.ajax);
- } else if ("data" in opts) {
- opts.query = local(opts.data);
- } else if ("tags" in opts) {
- opts.query = tags(opts.tags);
- if (opts.createSearchChoice === undefined) {
- opts.createSearchChoice = function (term) { return {id: $.trim(term), text: $.trim(term)}; };
- }
- if (opts.initSelection === undefined) {
- opts.initSelection = function (element, callback) {
- var data = [];
- $(splitVal(element.val(), opts.separator)).each(function () {
- var obj = { id: this, text: this },
- tags = opts.tags;
- if ($.isFunction(tags)) tags=tags();
- $(tags).each(function() { if (equal(this.id, obj.id)) { obj = this; return false; } });
- data.push(obj);
- });
-
- callback(data);
- };
- }
- }
- }
- }
- if (typeof(opts.query) !== "function") {
- throw "query function not defined for Select2 " + opts.element.attr("id");
- }
-
- if (opts.createSearchChoicePosition === 'top') {
- opts.createSearchChoicePosition = function(list, item) { list.unshift(item); };
- }
- else if (opts.createSearchChoicePosition === 'bottom') {
- opts.createSearchChoicePosition = function(list, item) { list.push(item); };
- }
- else if (typeof(opts.createSearchChoicePosition) !== "function") {
- throw "invalid createSearchChoicePosition option must be 'top', 'bottom' or a custom function";
- }
-
- return opts;
- },
-
- /**
- * Monitor the original element for changes and update select2 accordingly
- */
- // abstract
- monitorSource: function () {
- var el = this.opts.element, sync, observer;
-
- el.on("change.select2", this.bind(function (e) {
- if (this.opts.element.data("select2-change-triggered") !== true) {
- this.initSelection();
- }
- }));
-
- sync = this.bind(function () {
-
- // sync enabled state
- var disabled = el.prop("disabled");
- if (disabled === undefined) disabled = false;
- this.enable(!disabled);
-
- var readonly = el.prop("readonly");
- if (readonly === undefined) readonly = false;
- this.readonly(readonly);
-
- syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
- this.container.addClass(evaluate(this.opts.containerCssClass));
-
- syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);
- this.dropdown.addClass(evaluate(this.opts.dropdownCssClass));
-
- });
-
- // IE8-10
- el.on("propertychange.select2", sync);
-
- // hold onto a reference of the callback to work around a chromium bug
- if (this.mutationCallback === undefined) {
- this.mutationCallback = function (mutations) {
- mutations.forEach(sync);
- }
- }
-
- // safari, chrome, firefox, IE11
- observer = window.MutationObserver || window.WebKitMutationObserver|| window.MozMutationObserver;
- if (observer !== undefined) {
- if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; }
- this.propertyObserver = new observer(this.mutationCallback);
- this.propertyObserver.observe(el.get(0), { attributes:true, subtree:false });
- }
- },
-
- // abstract
- triggerSelect: function(data) {
- var evt = $.Event("select2-selecting", { val: this.id(data), object: data });
- this.opts.element.trigger(evt);
- return !evt.isDefaultPrevented();
- },
-
- /**
- * Triggers the change event on the source element
- */
- // abstract
- triggerChange: function (details) {
-
- details = details || {};
- details= $.extend({}, details, { type: "change", val: this.val() });
- // prevents recursive triggering
- this.opts.element.data("select2-change-triggered", true);
- this.opts.element.trigger(details);
- this.opts.element.data("select2-change-triggered", false);
-
- // some validation frameworks ignore the change event and listen instead to keyup, click for selects
- // so here we trigger the click event manually
- this.opts.element.click();
-
- // ValidationEngine ignores the change event and listens instead to blur
- // so here we trigger the blur event manually if so desired
- if (this.opts.blurOnChange)
- this.opts.element.blur();
- },
-
- //abstract
- isInterfaceEnabled: function()
- {
- return this.enabledInterface === true;
- },
-
- // abstract
- enableInterface: function() {
- var enabled = this._enabled && !this._readonly,
- disabled = !enabled;
-
- if (enabled === this.enabledInterface) return false;
-
- this.container.toggleClass("select2-container-disabled", disabled);
- this.close();
- this.enabledInterface = enabled;
-
- return true;
- },
-
- // abstract
- enable: function(enabled) {
- if (enabled === undefined) enabled = true;
- if (this._enabled === enabled) return;
- this._enabled = enabled;
-
- this.opts.element.prop("disabled", !enabled);
- this.enableInterface();
- },
-
- // abstract
- disable: function() {
- this.enable(false);
- },
-
- // abstract
- readonly: function(enabled) {
- if (enabled === undefined) enabled = false;
- if (this._readonly === enabled) return;
- this._readonly = enabled;
-
- this.opts.element.prop("readonly", enabled);
- this.enableInterface();
- },
-
- // abstract
- opened: function () {
- return this.container.hasClass("select2-dropdown-open");
- },
-
- // abstract
- positionDropdown: function() {
- var $dropdown = this.dropdown,
- offset = this.container.offset(),
- height = this.container.outerHeight(false),
- width = this.container.outerWidth(false),
- dropHeight = $dropdown.outerHeight(false),
- $window = $(window),
- windowWidth = $window.width(),
- windowHeight = $window.height(),
- viewPortRight = $window.scrollLeft() + windowWidth,
- viewportBottom = $window.scrollTop() + windowHeight,
- dropTop = offset.top + height,
- dropLeft = offset.left,
- enoughRoomBelow = dropTop + dropHeight <= viewportBottom,
- enoughRoomAbove = (offset.top - dropHeight) >= this.body().scrollTop(),
- dropWidth = $dropdown.outerWidth(false),
- enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight,
- aboveNow = $dropdown.hasClass("select2-drop-above"),
- bodyOffset,
- above,
- changeDirection,
- css,
- resultsListNode;
-
- // always prefer the current above/below alignment, unless there is not enough room
- if (aboveNow) {
- above = true;
- if (!enoughRoomAbove && enoughRoomBelow) {
- changeDirection = true;
- above = false;
- }
- } else {
- above = false;
- if (!enoughRoomBelow && enoughRoomAbove) {
- changeDirection = true;
- above = true;
- }
- }
-
- //if we are changing direction we need to get positions when dropdown is hidden;
- if (changeDirection) {
- $dropdown.hide();
- offset = this.container.offset();
- height = this.container.outerHeight(false);
- width = this.container.outerWidth(false);
- dropHeight = $dropdown.outerHeight(false);
- viewPortRight = $window.scrollLeft() + windowWidth;
- viewportBottom = $window.scrollTop() + windowHeight;
- dropTop = offset.top + height;
- dropLeft = offset.left;
- dropWidth = $dropdown.outerWidth(false);
- enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight;
- $dropdown.show();
- }
-
- if (this.opts.dropdownAutoWidth) {
- resultsListNode = $('.select2-results', $dropdown)[0];
- $dropdown.addClass('select2-drop-auto-width');
- $dropdown.css('width', '');
- // Add scrollbar width to dropdown if vertical scrollbar is present
- dropWidth = $dropdown.outerWidth(false) + (resultsListNode.scrollHeight === resultsListNode.clientHeight ? 0 : scrollBarDimensions.width);
- dropWidth > width ? width = dropWidth : dropWidth = width;
- enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight;
- }
- else {
- this.container.removeClass('select2-drop-auto-width');
- }
-
- //console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow);
- //console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove);
-
- // fix positioning when body has an offset and is not position: static
- if (this.body().css('position') !== 'static') {
- bodyOffset = this.body().offset();
- dropTop -= bodyOffset.top;
- dropLeft -= bodyOffset.left;
- }
-
- if (!enoughRoomOnRight) {
- dropLeft = offset.left + this.container.outerWidth(false) - dropWidth;
- }
-
- css = {
- left: dropLeft,
- width: width
- };
-
- if (above) {
- css.top = offset.top - dropHeight;
- css.bottom = 'auto';
- this.container.addClass("select2-drop-above");
- $dropdown.addClass("select2-drop-above");
- }
- else {
- css.top = dropTop;
- css.bottom = 'auto';
- this.container.removeClass("select2-drop-above");
- $dropdown.removeClass("select2-drop-above");
- }
- css = $.extend(css, evaluate(this.opts.dropdownCss));
-
- $dropdown.css(css);
- },
-
- // abstract
- shouldOpen: function() {
- var event;
-
- if (this.opened()) return false;
-
- if (this._enabled === false || this._readonly === true) return false;
-
- event = $.Event("select2-opening");
- this.opts.element.trigger(event);
- return !event.isDefaultPrevented();
- },
-
- // abstract
- clearDropdownAlignmentPreference: function() {
- // clear the classes used to figure out the preference of where the dropdown should be opened
- this.container.removeClass("select2-drop-above");
- this.dropdown.removeClass("select2-drop-above");
- },
-
- /**
- * Opens the dropdown
- *
- * @return {Boolean} whether or not dropdown was opened. This method will return false if, for example,
- * the dropdown is already open, or if the 'open' event listener on the element called preventDefault().
- */
- // abstract
- open: function () {
-
- if (!this.shouldOpen()) return false;
-
- this.opening();
-
- return true;
- },
-
- /**
- * Performs the opening of the dropdown
- */
- // abstract
- opening: function() {
- var cid = this.containerId,
- scroll = "scroll." + cid,
- resize = "resize."+cid,
- orient = "orientationchange."+cid,
- mask;
-
- this.container.addClass("select2-dropdown-open").addClass("select2-container-active");
-
- this.clearDropdownAlignmentPreference();
-
- if(this.dropdown[0] !== this.body().children().last()[0]) {
- this.dropdown.detach().appendTo(this.body());
- }
-
- // create the dropdown mask if doesn't already exist
- mask = $("#select2-drop-mask");
- if (mask.length == 0) {
- mask = $(document.createElement("div"));
- mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask");
- mask.hide();
- mask.appendTo(this.body());
- mask.on("mousedown touchstart click", function (e) {
- // Prevent IE from generating a click event on the body
- reinsertElement(mask);
-
- var dropdown = $("#select2-drop"), self;
- if (dropdown.length > 0) {
- self=dropdown.data("select2");
- if (self.opts.selectOnBlur) {
- self.selectHighlighted({noFocus: true});
- }
- self.close({focus:true});
- e.preventDefault();
- e.stopPropagation();
- }
- });
- }
-
- // ensure the mask is always right before the dropdown
- if (this.dropdown.prev()[0] !== mask[0]) {
- this.dropdown.before(mask);
- }
-
- // move the global id to the correct dropdown
- $("#select2-drop").removeAttr("id");
- this.dropdown.attr("id", "select2-drop");
-
- // show the elements
- mask.show();
-
- this.positionDropdown();
- this.dropdown.show();
- this.positionDropdown();
-
- this.dropdown.addClass("select2-drop-active");
-
- // attach listeners to events that can change the position of the container and thus require
- // the position of the dropdown to be updated as well so it does not come unglued from the container
- var that = this;
- this.container.parents().add(window).each(function () {
- $(this).on(resize+" "+scroll+" "+orient, function (e) {
- that.positionDropdown();
- });
- });
-
-
- },
-
- // abstract
- close: function () {
- if (!this.opened()) return;
-
- var cid = this.containerId,
- scroll = "scroll." + cid,
- resize = "resize."+cid,
- orient = "orientationchange."+cid;
-
- // unbind event listeners
- this.container.parents().add(window).each(function () { $(this).off(scroll).off(resize).off(orient); });
-
- this.clearDropdownAlignmentPreference();
-
- $("#select2-drop-mask").hide();
- this.dropdown.removeAttr("id"); // only the active dropdown has the select2-drop id
- this.dropdown.hide();
- this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active");
- this.results.empty();
-
-
- this.clearSearch();
- this.search.removeClass("select2-active");
- this.opts.element.trigger($.Event("select2-close"));
- },
-
- /**
- * Opens control, sets input value, and updates results.
- */
- // abstract
- externalSearch: function (term) {
- this.open();
- this.search.val(term);
- this.updateResults(false);
- },
-
- // abstract
- clearSearch: function () {
-
- },
-
- //abstract
- getMaximumSelectionSize: function() {
- return evaluate(this.opts.maximumSelectionSize);
- },
-
- // abstract
- ensureHighlightVisible: function () {
- var results = this.results, children, index, child, hb, rb, y, more;
-
- index = this.highlight();
-
- if (index < 0) return;
-
- if (index == 0) {
-
- // if the first element is highlighted scroll all the way to the top,
- // that way any unselectable headers above it will also be scrolled
- // into view
-
- results.scrollTop(0);
- return;
- }
-
- children = this.findHighlightableChoices().find('.select2-result-label');
-
- child = $(children[index]);
-
- hb = child.offset().top + child.outerHeight(true);
-
- // if this is the last child lets also make sure select2-more-results is visible
- if (index === children.length - 1) {
- more = results.find("li.select2-more-results");
- if (more.length > 0) {
- hb = more.offset().top + more.outerHeight(true);
- }
- }
-
- rb = results.offset().top + results.outerHeight(true);
- if (hb > rb) {
- results.scrollTop(results.scrollTop() + (hb - rb));
- }
- y = child.offset().top - results.offset().top;
-
- // make sure the top of the element is visible
- if (y < 0 && child.css('display') != 'none' ) {
- results.scrollTop(results.scrollTop() + y); // y is negative
- }
- },
-
- // abstract
- findHighlightableChoices: function() {
- return this.results.find(".select2-result-selectable:not(.select2-disabled):not(.select2-selected)");
- },
-
- // abstract
- moveHighlight: function (delta) {
- var choices = this.findHighlightableChoices(),
- index = this.highlight();
-
- while (index > -1 && index < choices.length) {
- index += delta;
- var choice = $(choices[index]);
- if (choice.hasClass("select2-result-selectable") && !choice.hasClass("select2-disabled") && !choice.hasClass("select2-selected")) {
- this.highlight(index);
- break;
- }
- }
- },
-
- // abstract
- highlight: function (index) {
- var choices = this.findHighlightableChoices(),
- choice,
- data;
-
- if (arguments.length === 0) {
- return indexOf(choices.filter(".select2-highlighted")[0], choices.get());
- }
-
- if (index >= choices.length) index = choices.length - 1;
- if (index < 0) index = 0;
-
- this.removeHighlight();
-
- choice = $(choices[index]);
- choice.addClass("select2-highlighted");
-
- // ensure assistive technology can determine the active choice
- this.search.attr("aria-activedescendant", choice.find(".select2-result-label").attr("id"));
-
- this.ensureHighlightVisible();
-
- this.liveRegion.text(choice.text());
-
- data = choice.data("select2-data");
- if (data) {
- this.opts.element.trigger({ type: "select2-highlight", val: this.id(data), choice: data });
- }
- },
-
- removeHighlight: function() {
- this.results.find(".select2-highlighted").removeClass("select2-highlighted");
- },
-
- // abstract
- countSelectableResults: function() {
- return this.findHighlightableChoices().length;
- },
-
- // abstract
- highlightUnderEvent: function (event) {
- var el = $(event.target).closest(".select2-result-selectable");
- if (el.length > 0 && !el.is(".select2-highlighted")) {
- var choices = this.findHighlightableChoices();
- this.highlight(choices.index(el));
- } else if (el.length == 0) {
- // if we are over an unselectable item remove all highlights
- this.removeHighlight();
- }
- },
-
- // abstract
- loadMoreIfNeeded: function () {
- var results = this.results,
- more = results.find("li.select2-more-results"),
- below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible
- page = this.resultsPage + 1,
- self=this,
- term=this.search.val(),
- context=this.context;
-
- if (more.length === 0) return;
- below = more.offset().top - results.offset().top - results.height();
-
- if (below <= this.opts.loadMorePadding) {
- more.addClass("select2-active");
- this.opts.query({
- element: this.opts.element,
- term: term,
- page: page,
- context: context,
- matcher: this.opts.matcher,
- callback: this.bind(function (data) {
-
- // ignore a response if the select2 has been closed before it was received
- if (!self.opened()) return;
-
-
- self.opts.populateResults.call(this, results, data.results, {term: term, page: page, context:context});
- self.postprocessResults(data, false, false);
-
- if (data.more===true) {
- more.detach().appendTo(results).text(self.opts.formatLoadMore(page+1));
- window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);
- } else {
- more.remove();
- }
- self.positionDropdown();
- self.resultsPage = page;
- self.context = data.context;
- this.opts.element.trigger({ type: "select2-loaded", items: data });
- })});
- }
- },
-
- /**
- * Default tokenizer function which does nothing
- */
- tokenize: function() {
-
- },
-
- /**
- * @param initial whether or not this is the call to this method right after the dropdown has been opened
- */
- // abstract
- updateResults: function (initial) {
- var search = this.search,
- results = this.results,
- opts = this.opts,
- data,
- self = this,
- input,
- term = search.val(),
- lastTerm = $.data(this.container, "select2-last-term"),
- // sequence number used to drop out-of-order responses
- queryNumber;
-
- // prevent duplicate queries against the same term
- if (initial !== true && lastTerm && equal(term, lastTerm)) return;
-
- $.data(this.container, "select2-last-term", term);
-
- // if the search is currently hidden we do not alter the results
- if (initial !== true && (this.showSearchInput === false || !this.opened())) {
- return;
- }
-
- function postRender() {
- search.removeClass("select2-active");
- self.positionDropdown();
- if (results.find('.select2-no-results,.select2-selection-limit,.select2-searching').length) {
- self.liveRegion.text(results.text());
- }
- else {
- self.liveRegion.text(self.opts.formatMatches(results.find('.select2-result-selectable').length));
- }
- }
-
- function render(html) {
- results.html(html);
- postRender();
- }
-
- queryNumber = ++this.queryCount;
-
- var maxSelSize = this.getMaximumSelectionSize();
- if (maxSelSize >=1) {
- data = this.data();
- if ($.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
- render("<li class='select2-selection-limit'>" + evaluate(opts.formatSelectionTooBig, maxSelSize) + "</li>");
- return;
- }
- }
-
- if (search.val().length < opts.minimumInputLength) {
- if (checkFormatter(opts.formatInputTooShort, "formatInputTooShort")) {
- render("<li class='select2-no-results'>" + evaluate(opts.formatInputTooShort, search.val(), opts.minimumInputLength) + "</li>");
- } else {
- render("");
- }
- if (initial && this.showSearch) this.showSearch(true);
- return;
- }
-
- if (opts.maximumInputLength && search.val().length > opts.maximumInputLength) {
- if (checkFormatter(opts.formatInputTooLong, "formatInputTooLong")) {
- render("<li class='select2-no-results'>" + evaluate(opts.formatInputTooLong, search.val(), opts.maximumInputLength) + "</li>");
- } else {
- render("");
- }
- return;
- }
-
- if (opts.formatSearching && this.findHighlightableChoices().length === 0) {
- render("<li class='select2-searching'>" + evaluate(opts.formatSearching) + "</li>");
- }
-
- search.addClass("select2-active");
-
- this.removeHighlight();
-
- // give the tokenizer a chance to pre-process the input
- input = this.tokenize();
- if (input != undefined && input != null) {
- search.val(input);
- }
-
- this.resultsPage = 1;
-
- opts.query({
- element: opts.element,
- term: search.val(),
- page: this.resultsPage,
- context: null,
- matcher: opts.matcher,
- callback: this.bind(function (data) {
- var def; // default choice
-
- // ignore old responses
- if (queryNumber != this.queryCount) {
- return;
- }
-
- // ignore a response if the select2 has been closed before it was received
- if (!this.opened()) {
- this.search.removeClass("select2-active");
- return;
- }
-
- // save context, if any
- this.context = (data.context===undefined) ? null : data.context;
- // create a default choice and prepend it to the list
- if (this.opts.createSearchChoice && search.val() !== "") {
- def = this.opts.createSearchChoice.call(self, search.val(), data.results);
- if (def !== undefined && def !== null && self.id(def) !== undefined && self.id(def) !== null) {
- if ($(data.results).filter(
- function () {
- return equal(self.id(this), self.id(def));
- }).length === 0) {
- this.opts.createSearchChoicePosition(data.results, def);
- }
- }
- }
-
- if (data.results.length === 0 && checkFormatter(opts.formatNoMatches, "formatNoMatches")) {
- render("<li class='select2-no-results'>" + evaluate(opts.formatNoMatches, search.val()) + "</li>");
- return;
- }
-
- results.empty();
- self.opts.populateResults.call(this, results, data.results, {term: search.val(), page: this.resultsPage, context:null});
-
- if (data.more === true && checkFormatter(opts.formatLoadMore, "formatLoadMore")) {
- results.append("<li class='select2-more-results'>" + self.opts.escapeMarkup(evaluate(opts.formatLoadMore, this.resultsPage)) + "</li>");
- window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);
- }
-
- this.postprocessResults(data, initial);
-
- postRender();
-
- this.opts.element.trigger({ type: "select2-loaded", items: data });
- })});
- },
-
- // abstract
- cancel: function () {
- this.close();
- },
-
- // abstract
- blur: function () {
- // if selectOnBlur == true, select the currently highlighted option
- if (this.opts.selectOnBlur)
- this.selectHighlighted({noFocus: true});
-
- this.close();
- this.container.removeClass("select2-container-active");
- // synonymous to .is(':focus'), which is available in jquery >= 1.6
- if (this.search[0] === document.activeElement) { this.search.blur(); }
- this.clearSearch();
- this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
- },
-
- // abstract
- focusSearch: function () {
- focus(this.search);
- },
-
- // abstract
- selectHighlighted: function (options) {
- var index=this.highlight(),
- highlighted=this.results.find(".select2-highlighted"),
- data = highlighted.closest('.select2-result').data("select2-data");
-
- if (data) {
- this.highlight(index);
- this.onSelect(data, options);
- } else if (options && options.noFocus) {
- this.close();
- }
- },
-
- // abstract
- getPlaceholder: function () {
- var placeholderOption;
- return this.opts.element.attr("placeholder") ||
- this.opts.element.attr("data-placeholder") || // jquery 1.4 compat
- this.opts.element.data("placeholder") ||
- this.opts.placeholder ||
- ((placeholderOption = this.getPlaceholderOption()) !== undefined ? placeholderOption.text() : undefined);
- },
-
- // abstract
- getPlaceholderOption: function() {
- if (this.select) {
- var firstOption = this.select.children('option').first();
- if (this.opts.placeholderOption !== undefined ) {
- //Determine the placeholder option based on the specified placeholderOption setting
- return (this.opts.placeholderOption === "first" && firstOption) ||
- (typeof this.opts.placeholderOption === "function" && this.opts.placeholderOption(this.select));
- } else if (firstOption.text() === "" && firstOption.val() === "") {
- //No explicit placeholder option specified, use the first if it's blank
- return firstOption;
- }
- }
- },
-
- /**
- * Get the desired width for the container element. This is
- * derived first from option `width` passed to select2, then
- * the inline 'style' on the original element, and finally
- * falls back to the jQuery calculated element width.
- */
- // abstract
- initContainerWidth: function () {
- function resolveContainerWidth() {
- var style, attrs, matches, i, l, attr;
-
- if (this.opts.width === "off") {
- return null;
- } else if (this.opts.width === "element"){
- return this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px';
- } else if (this.opts.width === "copy" || this.opts.width === "resolve") {
- // check if there is inline style on the element that contains width
- style = this.opts.element.attr('style');
- if (style !== undefined) {
- attrs = style.split(';');
- for (i = 0, l = attrs.length; i < l; i = i + 1) {
- attr = attrs[i].replace(/\s/g, '');
- matches = attr.match(/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i);
- if (matches !== null && matches.length >= 1)
- return matches[1];
- }
- }
-
- if (this.opts.width === "resolve") {
- // next check if css('width') can resolve a width that is percent based, this is sometimes possible
- // when attached to input type=hidden or elements hidden via css
- style = this.opts.element.css('width');
- if (style.indexOf("%") > 0) return style;
-
- // finally, fallback on the calculated width of the element
- return (this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px');
- }
-
- return null;
- } else if ($.isFunction(this.opts.width)) {
- return this.opts.width();
- } else {
- return this.opts.width;
- }
- };
-
- var width = resolveContainerWidth.call(this);
- if (width !== null) {
- this.container.css("width", width);
- }
- }
- });
-
- SingleSelect2 = clazz(AbstractSelect2, {
-
- // single
-
- createContainer: function () {
- var container = $(document.createElement("div")).attr({
- "class": "select2-container"
- }).html([
- "<a href='javascript:void(0)' onclick='return false;' class='select2-choice' tabindex='-1'>",
- " <span class='select2-chosen'>&nbsp;</span><abbr class='select2-search-choice-close'></abbr>",
- " <span class='select2-arrow' role='presentation'><b role='presentation'></b></span>",
- "</a>",
- "<label for='' class='select2-offscreen'></label>",
- "<input class='select2-focusser select2-offscreen' type='text' aria-haspopup='true' role='button' />",
- "<div class='select2-drop select2-display-none'>",
- " <div class='select2-search'>",
- " <label for='' class='select2-offscreen'></label>",
- " <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input' role='combobox' aria-expanded='true'",
- " aria-autocomplete='list' />",
- " </div>",
- " <ul class='select2-results' role='listbox'>",
- " </ul>",
- "</div>"].join(""));
- return container;
- },
-
- // single
- enableInterface: function() {
- if (this.parent.enableInterface.apply(this, arguments)) {
- this.focusser.prop("disabled", !this.isInterfaceEnabled());
- }
- },
-
- // single
- opening: function () {
- var el, range, len;
-
- if (this.opts.minimumResultsForSearch >= 0) {
- this.showSearch(true);
- }
-
- this.parent.opening.apply(this, arguments);
-
- if (this.showSearchInput !== false) {
- // IE appends focusser.val() at the end of field :/ so we manually insert it at the beginning using a range
- // all other browsers handle this just fine
-
- this.search.val(this.focusser.val());
- }
- this.search.focus();
- // move the cursor to the end after focussing, otherwise it will be at the beginning and
- // new text will appear *before* focusser.val()
- el = this.search.get(0);
- if (el.createTextRange) {
- range = el.createTextRange();
- range.collapse(false);
- range.select();
- } else if (el.setSelectionRange) {
- len = this.search.val().length;
- el.setSelectionRange(len, len);
- }
-
- // initializes search's value with nextSearchTerm (if defined by user)
- // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter
- if(this.search.val() === "") {
- if(this.nextSearchTerm != undefined){
- this.search.val(this.nextSearchTerm);
- this.search.select();
- }
- }
-
- this.focusser.prop("disabled", true).val("");
- this.updateResults(true);
- this.opts.element.trigger($.Event("select2-open"));
- },
-
- // single
- close: function (params) {
- if (!this.opened()) return;
- this.parent.close.apply(this, arguments);
-
- params = params || {focus: true};
- this.focusser.prop("disabled", false);
-
- if (params.focus) {
- this.focusser.focus();
- }
- },
-
- // single
- focus: function () {
- if (this.opened()) {
- this.close();
- } else {
- this.focusser.prop("disabled", false);
- this.focusser.focus();
- }
- },
-
- // single
- isFocused: function () {
- return this.container.hasClass("select2-container-active");
- },
-
- // single
- cancel: function () {
- this.parent.cancel.apply(this, arguments);
- this.focusser.prop("disabled", false);
- this.focusser.focus();
- },
-
- // single
- destroy: function() {
- $("label[for='" + this.focusser.attr('id') + "']")
- .attr('for', this.opts.element.attr("id"));
- this.parent.destroy.apply(this, arguments);
- },
-
- // single
- initContainer: function () {
-
- var selection,
- container = this.container,
- dropdown = this.dropdown,
- idSuffix = nextUid(),
- elementLabel;
-
- if (this.opts.minimumResultsForSearch < 0) {
- this.showSearch(false);
- } else {
- this.showSearch(true);
- }
-
- this.selection = selection = container.find(".select2-choice");
-
- this.focusser = container.find(".select2-focusser");
-
- // add aria associations
- selection.find(".select2-chosen").attr("id", "select2-chosen-"+idSuffix);
- this.focusser.attr("aria-labelledby", "select2-chosen-"+idSuffix);
- this.results.attr("id", "select2-results-"+idSuffix);
- this.search.attr("aria-owns", "select2-results-"+idSuffix);
-
- // rewrite labels from original element to focusser
- this.focusser.attr("id", "s2id_autogen"+idSuffix);
-
- elementLabel = $("label[for='" + this.opts.element.attr("id") + "']");
-
- this.focusser.prev()
- .text(elementLabel.text())
- .attr('for', this.focusser.attr('id'));
-
- // Ensure the original element retains an accessible name
- var originalTitle = this.opts.element.attr("title");
- this.opts.element.attr("title", (originalTitle || elementLabel.text()));
-
- this.focusser.attr("tabindex", this.elementTabIndex);
-
- // write label for search field using the label from the focusser element
- this.search.attr("id", this.focusser.attr('id') + '_search');
-
- this.search.prev()
- .text($("label[for='" + this.focusser.attr('id') + "']").text())
- .attr('for', this.search.attr('id'));
-
- this.search.on("keydown", this.bind(function (e) {
- if (!this.isInterfaceEnabled()) return;
-
- if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {
- // prevent the page from scrolling
- killEvent(e);
- return;
- }
-
- switch (e.which) {
- case KEY.UP:
- case KEY.DOWN:
- this.moveHighlight((e.which === KEY.UP) ? -1 : 1);
- killEvent(e);
- return;
- case KEY.ENTER:
- this.selectHighlighted();
- killEvent(e);
- return;
- case KEY.TAB:
- this.selectHighlighted({noFocus: true});
- return;
- case KEY.ESC:
- this.cancel(e);
- killEvent(e);
- return;
- }
- }));
-
- this.search.on("blur", this.bind(function(e) {
- // a workaround for chrome to keep the search field focussed when the scroll bar is used to scroll the dropdown.
- // without this the search field loses focus which is annoying
- if (document.activeElement === this.body().get(0)) {
- window.setTimeout(this.bind(function() {
- if (this.opened()) {
- this.search.focus();
- }
- }), 0);
- }
- }));
-
- this.focusser.on("keydown", this.bind(function (e) {
- if (!this.isInterfaceEnabled()) return;
-
- if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
- return;
- }
-
- if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
- killEvent(e);
- return;
- }
-
- if (e.which == KEY.DOWN || e.which == KEY.UP
- || (e.which == KEY.ENTER && this.opts.openOnEnter)) {
-
- if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) return;
-
- this.open();
- killEvent(e);
- return;
- }
-
- if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) {
- if (this.opts.allowClear) {
- this.clear();
- }
- killEvent(e);
- return;
- }
- }));
-
-
- installKeyUpChangeEvent(this.focusser);
- this.focusser.on("keyup-change input", this.bind(function(e) {
- if (this.opts.minimumResultsForSearch >= 0) {
- e.stopPropagation();
- if (this.opened()) return;
- this.open();
- }
- }));
-
- selection.on("mousedown touchstart", "abbr", this.bind(function (e) {
- if (!this.isInterfaceEnabled()) return;
- this.clear();
- killEventImmediately(e);
- this.close();
- this.selection.focus();
- }));
-
- selection.on("mousedown touchstart", this.bind(function (e) {
- // Prevent IE from generating a click event on the body
- reinsertElement(selection);
-
- if (!this.container.hasClass("select2-container-active")) {
- this.opts.element.trigger($.Event("select2-focus"));
- }
-
- if (this.opened()) {
- this.close();
- } else if (this.isInterfaceEnabled()) {
- this.open();
- }
-
- killEvent(e);
- }));
-
- dropdown.on("mousedown touchstart", this.bind(function() { this.search.focus(); }));
-
- selection.on("focus", this.bind(function(e) {
- killEvent(e);
- }));
-
- this.focusser.on("focus", this.bind(function(){
- if (!this.container.hasClass("select2-container-active")) {
- this.opts.element.trigger($.Event("select2-focus"));
- }
- this.container.addClass("select2-container-active");
- })).on("blur", this.bind(function() {
- if (!this.opened()) {
- this.container.removeClass("select2-container-active");
- this.opts.element.trigger($.Event("select2-blur"));
- }
- }));
- this.search.on("focus", this.bind(function(){
- if (!this.container.hasClass("select2-container-active")) {
- this.opts.element.trigger($.Event("select2-focus"));
- }
- this.container.addClass("select2-container-active");
- }));
-
- this.initContainerWidth();
- this.opts.element.addClass("select2-offscreen");
- this.setPlaceholder();
-
- },
-
- // single
- clear: function(triggerChange) {
- var data=this.selection.data("select2-data");
- if (data) { // guard against queued quick consecutive clicks
- var evt = $.Event("select2-clearing");
- this.opts.element.trigger(evt);
- if (evt.isDefaultPrevented()) {
- return;
- }
- var placeholderOption = this.getPlaceholderOption();
- this.opts.element.val(placeholderOption ? placeholderOption.val() : "");
- this.selection.find(".select2-chosen").empty();
- this.selection.removeData("select2-data");
- this.setPlaceholder();
-
- if (triggerChange !== false){
- this.opts.element.trigger({ type: "select2-removed", val: this.id(data), choice: data });
- this.triggerChange({removed:data});
- }
- }
- },
-
- /**
- * Sets selection based on source element's value
- */
- // single
- initSelection: function () {
- var selected;
- if (this.isPlaceholderOptionSelected()) {
- this.updateSelection(null);
- this.close();
- this.setPlaceholder();
- } else {
- var self = this;
- this.opts.initSelection.call(null, this.opts.element, function(selected){
- if (selected !== undefined && selected !== null) {
- self.updateSelection(selected);
- self.close();
- self.setPlaceholder();
- self.nextSearchTerm = self.opts.nextSearchTerm(selected, self.search.val());
- }
- });
- }
- },
-
- isPlaceholderOptionSelected: function() {
- var placeholderOption;
- if (!this.getPlaceholder()) return false; // no placeholder specified so no option should be considered
- return ((placeholderOption = this.getPlaceholderOption()) !== undefined && placeholderOption.prop("selected"))
- || (this.opts.element.val() === "")
- || (this.opts.element.val() === undefined)
- || (this.opts.element.val() === null);
- },
-
- // single
- prepareOpts: function () {
- var opts = this.parent.prepareOpts.apply(this, arguments),
- self=this;
-
- if (opts.element.get(0).tagName.toLowerCase() === "select") {
- // install the selection initializer
- opts.initSelection = function (element, callback) {
- var selected = element.find("option").filter(function() { return this.selected });
- // a single select box always has a value, no need to null check 'selected'
- callback(self.optionToData(selected));
- };
- } else if ("data" in opts) {
- // install default initSelection when applied to hidden input and data is local
- opts.initSelection = opts.initSelection || function (element, callback) {
- var id = element.val();
- //search in data by id, storing the actual matching item
- var match = null;
- opts.query({
- matcher: function(term, text, el){
- var is_match = equal(id, opts.id(el));
- if (is_match) {
- match = el;
- }
- return is_match;
- },
- callback: !$.isFunction(callback) ? $.noop : function() {
- callback(match);
- }
- });
- };
- }
-
- return opts;
- },
-
- // single
- getPlaceholder: function() {
- // if a placeholder is specified on a single select without a valid placeholder option ignore it
- if (this.select) {
- if (this.getPlaceholderOption() === undefined) {
- return undefined;
- }
- }
-
- return this.parent.getPlaceholder.apply(this, arguments);
- },
-
- // single
- setPlaceholder: function () {
- var placeholder = this.getPlaceholder();
-
- if (this.isPlaceholderOptionSelected() && placeholder !== undefined) {
-
- // check for a placeholder option if attached to a select
- if (this.select && this.getPlaceholderOption() === undefined) return;
-
- this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(placeholder));
-
- this.selection.addClass("select2-default");
-
- this.container.removeClass("select2-allowclear");
- }
- },
-
- // single
- postprocessResults: function (data, initial, noHighlightUpdate) {
- var selected = 0, selectedElm = null, self = this, showSearchInput = true;
-
- // find the selected element in the result list
-
- this.findHighlightableChoices().each2(function (i, elm) {
- if (equal(self.id(elm.data("select2-data")), self.opts.element.val())) {
- selected = i;
- selectedElm = elm;
- return false;
- }
- });
-
- // and highlight it
- if (noHighlightUpdate !== false) {
- if (initial === true && selected >= 0) {
- // By default, the selected item is displayed inside the result list from a single select
- // User can provide an implementation for 'hideSelectionFromResult' and hide it
- if(selectedElm !== null) {
- if(this.opts.hideSelectionFromResult(selectedElm))
- selectedElm.addClass("select2-selected");
- }
- else
- this.highlight(selected);
- } else {
- this.highlight(0);
- }
- }
-
- // hide the search box if this is the first we got the results and there are enough of them for search
-
- if (initial === true) {
- var min = this.opts.minimumResultsForSearch;
- if (min >= 0) {
- this.showSearch(countResults(data.results) >= min);
- }
- }
- },
-
- // single
- showSearch: function(showSearchInput) {
- if (this.showSearchInput === showSearchInput) return;
-
- this.showSearchInput = showSearchInput;
-
- this.dropdown.find(".select2-search").toggleClass("select2-search-hidden", !showSearchInput);
- this.dropdown.find(".select2-search").toggleClass("select2-offscreen", !showSearchInput);
- //add "select2-with-searchbox" to the container if search box is shown
- $(this.dropdown, this.container).toggleClass("select2-with-searchbox", showSearchInput);
- },
-
- // single
- onSelect: function (data, options) {
-
- if (!this.triggerSelect(data)) { return; }
-
- var old = this.opts.element.val(),
- oldData = this.data();
-
- this.opts.element.val(this.id(data));
- this.updateSelection(data);
-
- this.opts.element.trigger({ type: "select2-selected", val: this.id(data), choice: data });
-
- this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val());
- this.close();
-
- if (!options || !options.noFocus)
- this.focusser.focus();
-
- if (!equal(old, this.id(data))) { this.triggerChange({added:data,removed:oldData}); }
- },
-
- // single
- updateSelection: function (data) {
-
- var container=this.selection.find(".select2-chosen"), formatted, cssClass;
-
- this.selection.data("select2-data", data);
-
- container.empty();
- if (data !== null) {
- formatted=this.opts.formatSelection(data, container, this.opts.escapeMarkup);
- }
- if (formatted !== undefined) {
- container.append(formatted);
- }
- cssClass=this.opts.formatSelectionCssClass(data, container);
- if (cssClass !== undefined) {
- container.addClass(cssClass);
- }
-
- this.selection.removeClass("select2-default");
-
- if (this.opts.allowClear && this.getPlaceholder() !== undefined) {
- this.container.addClass("select2-allowclear");
- }
- },
-
- // single
- val: function () {
- var val,
- triggerChange = false,
- data = null,
- self = this,
- oldData = this.data();
-
- if (arguments.length === 0) {
- return this.opts.element.val();
- }
-
- val = arguments[0];
-
- if (arguments.length > 1) {
- triggerChange = arguments[1];
- }
-
- if (this.select) {
- this.select
- .val(val)
- .find("option").filter(function() { return this.selected }).each2(function (i, elm) {
- data = self.optionToData(elm);
- return false;
- });
- this.updateSelection(data);
- this.setPlaceholder();
- if (triggerChange) {
- this.triggerChange({added: data, removed:oldData});
- }
- } else {
- // val is an id. !val is true for [undefined,null,'',0] - 0 is legal
- if (!val && val !== 0) {
- this.clear(triggerChange);
- return;
- }
- if (this.opts.initSelection === undefined) {
- throw new Error("cannot call val() if initSelection() is not defined");
- }
- this.opts.element.val(val);
- this.opts.initSelection(this.opts.element, function(data){
- self.opts.element.val(!data ? "" : self.id(data));
- self.updateSelection(data);
- self.setPlaceholder();
- if (triggerChange) {
- self.triggerChange({added: data, removed:oldData});
- }
- });
- }
- },
-
- // single
- clearSearch: function () {
- this.search.val("");
- this.focusser.val("");
- },
-
- // single
- data: function(value) {
- var data,
- triggerChange = false;
-
- if (arguments.length === 0) {
- data = this.selection.data("select2-data");
- if (data == undefined) data = null;
- return data;
- } else {
- if (arguments.length > 1) {
- triggerChange = arguments[1];
- }
- if (!value) {
- this.clear(triggerChange);
- } else {
- data = this.data();
- this.opts.element.val(!value ? "" : this.id(value));
- this.updateSelection(value);
- if (triggerChange) {
- this.triggerChange({added: value, removed:data});
- }
- }
- }
- }
- });
-
- MultiSelect2 = clazz(AbstractSelect2, {
-
- // multi
- createContainer: function () {
- var container = $(document.createElement("div")).attr({
- "class": "select2-container select2-container-multi"
- }).html([
- "<ul class='select2-choices'>",
- " <li class='select2-search-field'>",
- " <label for='' class='select2-offscreen'></label>",
- " <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input'>",
- " </li>",
- "</ul>",
- "<div class='select2-drop select2-drop-multi select2-display-none'>",
- " <ul class='select2-results'>",
- " </ul>",
- "</div>"].join(""));
- return container;
- },
-
- // multi
- prepareOpts: function () {
- var opts = this.parent.prepareOpts.apply(this, arguments),
- self=this;
-
- // TODO validate placeholder is a string if specified
-
- if (opts.element.get(0).tagName.toLowerCase() === "select") {
- // install the selection initializer
- opts.initSelection = function (element, callback) {
-
- var data = [];
-
- element.find("option").filter(function() { return this.selected }).each2(function (i, elm) {
- data.push(self.optionToData(elm));
- });
- callback(data);
- };
- } else if ("data" in opts) {
- // install default initSelection when applied to hidden input and data is local
- opts.initSelection = opts.initSelection || function (element, callback) {
- var ids = splitVal(element.val(), opts.separator);
- //search in data by array of ids, storing matching items in a list
- var matches = [];
- opts.query({
- matcher: function(term, text, el){
- var is_match = $.grep(ids, function(id) {
- return equal(id, opts.id(el));
- }).length;
- if (is_match) {
- matches.push(el);
- }
- return is_match;
- },
- callback: !$.isFunction(callback) ? $.noop : function() {
- // reorder matches based on the order they appear in the ids array because right now
- // they are in the order in which they appear in data array
- var ordered = [];
- for (var i = 0; i < ids.length; i++) {
- var id = ids[i];
- for (var j = 0; j < matches.length; j++) {
- var match = matches[j];
- if (equal(id, opts.id(match))) {
- ordered.push(match);
- matches.splice(j, 1);
- break;
- }
- }
- }
- callback(ordered);
- }
- });
- };
- }
-
- return opts;
- },
-
- // multi
- selectChoice: function (choice) {
-
- var selected = this.container.find(".select2-search-choice-focus");
- if (selected.length && choice && choice[0] == selected[0]) {
-
- } else {
- if (selected.length) {
- this.opts.element.trigger("choice-deselected", selected);
- }
- selected.removeClass("select2-search-choice-focus");
- if (choice && choice.length) {
- this.close();
- choice.addClass("select2-search-choice-focus");
- this.opts.element.trigger("choice-selected", choice);
- }
- }
- },
-
- // multi
- destroy: function() {
- $("label[for='" + this.search.attr('id') + "']")
- .attr('for', this.opts.element.attr("id"));
- this.parent.destroy.apply(this, arguments);
- },
-
- // multi
- initContainer: function () {
-
- var selector = ".select2-choices", selection;
-
- this.searchContainer = this.container.find(".select2-search-field");
- this.selection = selection = this.container.find(selector);
-
- var _this = this;
- this.selection.on("click", ".select2-search-choice:not(.select2-locked)", function (e) {
- //killEvent(e);
- _this.search[0].focus();
- _this.selectChoice($(this));
- });
-
- // rewrite labels from original element to focusser
- this.search.attr("id", "s2id_autogen"+nextUid());
-
- this.search.prev()
- .text($("label[for='" + this.opts.element.attr("id") + "']").text())
- .attr('for', this.search.attr('id'));
-
- this.search.on("input paste", this.bind(function() {
- if (!this.isInterfaceEnabled()) return;
- if (!this.opened()) {
- this.open();
- }
- }));
-
- this.search.attr("tabindex", this.elementTabIndex);
-
- this.keydowns = 0;
- this.search.on("keydown", this.bind(function (e) {
- if (!this.isInterfaceEnabled()) return;
-
- ++this.keydowns;
- var selected = selection.find(".select2-search-choice-focus");
- var prev = selected.prev(".select2-search-choice:not(.select2-locked)");
- var next = selected.next(".select2-search-choice:not(.select2-locked)");
- var pos = getCursorInfo(this.search);
-
- if (selected.length &&
- (e.which == KEY.LEFT || e.which == KEY.RIGHT || e.which == KEY.BACKSPACE || e.which == KEY.DELETE || e.which == KEY.ENTER)) {
- var selectedChoice = selected;
- if (e.which == KEY.LEFT && prev.length) {
- selectedChoice = prev;
- }
- else if (e.which == KEY.RIGHT) {
- selectedChoice = next.length ? next : null;
- }
- else if (e.which === KEY.BACKSPACE) {
- this.unselect(selected.first());
- this.search.width(10);
- selectedChoice = prev.length ? prev : next;
- } else if (e.which == KEY.DELETE) {
- this.unselect(selected.first());
- this.search.width(10);
- selectedChoice = next.length ? next : null;
- } else if (e.which == KEY.ENTER) {
- selectedChoice = null;
- }
-
- this.selectChoice(selectedChoice);
- killEvent(e);
- if (!selectedChoice || !selectedChoice.length) {
- this.open();
- }
- return;
- } else if (((e.which === KEY.BACKSPACE && this.keydowns == 1)
- || e.which == KEY.LEFT) && (pos.offset == 0 && !pos.length)) {
-
- this.selectChoice(selection.find(".select2-search-choice:not(.select2-locked)").last());
- killEvent(e);
- return;
- } else {
- this.selectChoice(null);
- }
-
- if (this.opened()) {
- switch (e.which) {
- case KEY.UP:
- case KEY.DOWN:
- this.moveHighlight((e.which === KEY.UP) ? -1 : 1);
- killEvent(e);
- return;
- case KEY.ENTER:
- this.selectHighlighted();
- killEvent(e);
- return;
- case KEY.TAB:
- this.selectHighlighted({noFocus:true});
- this.close();
- return;
- case KEY.ESC:
- this.cancel(e);
- killEvent(e);
- return;
- }
- }
-
- if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e)
- || e.which === KEY.BACKSPACE || e.which === KEY.ESC) {
- return;
- }
-
- if (e.which === KEY.ENTER) {
- if (this.opts.openOnEnter === false) {
- return;
- } else if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
- return;
- }
- }
-
- this.open();
-
- if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {
- // prevent the page from scrolling
- killEvent(e);
- }
-
- if (e.which === KEY.ENTER) {
- // prevent form from being submitted
- killEvent(e);
- }
-
- }));
-
- this.search.on("keyup", this.bind(function (e) {
- this.keydowns = 0;
- this.resizeSearch();
- })
- );
-
- this.search.on("blur", this.bind(function(e) {
- this.container.removeClass("select2-container-active");
- this.search.removeClass("select2-focused");
- this.selectChoice(null);
- if (!this.opened()) this.clearSearch();
- e.stopImmediatePropagation();
- this.opts.element.trigger($.Event("select2-blur"));
- }));
-
- this.container.on("click", selector, this.bind(function (e) {
- if (!this.isInterfaceEnabled()) return;
- if ($(e.target).closest(".select2-search-choice").length > 0) {
- // clicked inside a select2 search choice, do not open
- return;
- }
- this.selectChoice(null);
- this.clearPlaceholder();
- if (!this.container.hasClass("select2-container-active")) {
- this.opts.element.trigger($.Event("select2-focus"));
- }
- this.open();
- this.focusSearch();
- e.preventDefault();
- }));
-
- this.container.on("focus", selector, this.bind(function () {
- if (!this.isInterfaceEnabled()) return;
- if (!this.container.hasClass("select2-container-active")) {
- this.opts.element.trigger($.Event("select2-focus"));
- }
- this.container.addClass("select2-container-active");
- this.dropdown.addClass("select2-drop-active");
- this.clearPlaceholder();
- }));
-
- this.initContainerWidth();
- this.opts.element.addClass("select2-offscreen");
-
- // set the placeholder if necessary
- this.clearSearch();
- },
-
- // multi
- enableInterface: function() {
- if (this.parent.enableInterface.apply(this, arguments)) {
- this.search.prop("disabled", !this.isInterfaceEnabled());
- }
- },
-
- // multi
- initSelection: function () {
- var data;
- if (this.opts.element.val() === "" && this.opts.element.text() === "") {
- this.updateSelection([]);
- this.close();
- // set the placeholder if necessary
- this.clearSearch();
- }
- if (this.select || this.opts.element.val() !== "") {
- var self = this;
- this.opts.initSelection.call(null, this.opts.element, function(data){
- if (data !== undefined && data !== null) {
- self.updateSelection(data);
- self.close();
- // set the placeholder if necessary
- self.clearSearch();
- }
- });
- }
- },
-
- // multi
- clearSearch: function () {
- var placeholder = this.getPlaceholder(),
- maxWidth = this.getMaxSearchWidth();
-
- if (placeholder !== undefined && this.getVal().length === 0 && this.search.hasClass("select2-focused") === false) {
- this.search.val(placeholder).addClass("select2-default");
- // stretch the search box to full width of the container so as much of the placeholder is visible as possible
- // we could call this.resizeSearch(), but we do not because that requires a sizer and we do not want to create one so early because of a firefox bug, see #944
- this.search.width(maxWidth > 0 ? maxWidth : this.container.css("width"));
- } else {
- this.search.val("").width(10);
- }
- },
-
- // multi
- clearPlaceholder: function () {
- if (this.search.hasClass("select2-default")) {
- this.search.val("").removeClass("select2-default");
- }
- },
-
- // multi
- opening: function () {
- this.clearPlaceholder(); // should be done before super so placeholder is not used to search
- this.resizeSearch();
-
- this.parent.opening.apply(this, arguments);
-
- this.focusSearch();
-
- // initializes search's value with nextSearchTerm (if defined by user)
- // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter
- if(this.search.val() === "") {
- if(this.nextSearchTerm != undefined){
- this.search.val(this.nextSearchTerm);
- this.search.select();
- }
- }
-
- this.updateResults(true);
- this.search.focus();
- this.opts.element.trigger($.Event("select2-open"));
- },
-
- // multi
- close: function () {
- if (!this.opened()) return;
- this.parent.close.apply(this, arguments);
- },
-
- // multi
- focus: function () {
- this.close();
- this.search.focus();
- },
-
- // multi
- isFocused: function () {
- return this.search.hasClass("select2-focused");
- },
-
- // multi
- updateSelection: function (data) {
- var ids = [], filtered = [], self = this;
-
- // filter out duplicates
- $(data).each(function () {
- if (indexOf(self.id(this), ids) < 0) {
- ids.push(self.id(this));
- filtered.push(this);
- }
- });
- data = filtered;
-
- this.selection.find(".select2-search-choice").remove();
- $(data).each(function () {
- self.addSelectedChoice(this);
- });
- self.postprocessResults();
- },
-
- // multi
- tokenize: function() {
- var input = this.search.val();
- input = this.opts.tokenizer.call(this, input, this.data(), this.bind(this.onSelect), this.opts);
- if (input != null && input != undefined) {
- this.search.val(input);
- if (input.length > 0) {
- this.open();
- }
- }
-
- },
-
- // multi
- onSelect: function (data, options) {
-
- if (!this.triggerSelect(data)) { return; }
-
- this.addSelectedChoice(data);
-
- this.opts.element.trigger({ type: "selected", val: this.id(data), choice: data });
-
- // keep track of the search's value before it gets cleared
- this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val());
-
- this.clearSearch();
- this.updateResults();
-
- if (this.select || !this.opts.closeOnSelect) this.postprocessResults(data, false, this.opts.closeOnSelect===true);
-
- if (this.opts.closeOnSelect) {
- this.close();
- this.search.width(10);
- } else {
- if (this.countSelectableResults()>0) {
- this.search.width(10);
- this.resizeSearch();
- if (this.getMaximumSelectionSize() > 0 && this.val().length >= this.getMaximumSelectionSize()) {
- // if we reached max selection size repaint the results so choices
- // are replaced with the max selection reached message
- this.updateResults(true);
- } else {
- // initializes search's value with nextSearchTerm and update search result
- if(this.nextSearchTerm != undefined){
- this.search.val(this.nextSearchTerm);
- this.updateResults();
- this.search.select();
- }
- }
- this.positionDropdown();
- } else {
- // if nothing left to select close
- this.close();
- this.search.width(10);
- }
- }
-
- // since its not possible to select an element that has already been
- // added we do not need to check if this is a new element before firing change
- this.triggerChange({ added: data });
-
- if (!options || !options.noFocus)
- this.focusSearch();
- },
-
- // multi
- cancel: function () {
- this.close();
- this.focusSearch();
- },
-
- addSelectedChoice: function (data) {
- var enableChoice = !data.locked,
- enabledItem = $(
- "<li class='select2-search-choice'>" +
- " <div></div>" +
- " <a href='#' onclick='return false;' class='select2-search-choice-close' tabindex='-1'></a>" +
- "</li>"),
- disabledItem = $(
- "<li class='select2-search-choice select2-locked'>" +
- "<div></div>" +
- "</li>");
- var choice = enableChoice ? enabledItem : disabledItem,
- id = this.id(data),
- val = this.getVal(),
- formatted,
- cssClass;
-
- formatted=this.opts.formatSelection(data, choice.find("div"), this.opts.escapeMarkup);
- if (formatted != undefined) {
- choice.find("div").replaceWith("<div>"+formatted+"</div>");
- }
- cssClass=this.opts.formatSelectionCssClass(data, choice.find("div"));
- if (cssClass != undefined) {
- choice.addClass(cssClass);
- }
-
- if(enableChoice){
- choice.find(".select2-search-choice-close")
- .on("mousedown", killEvent)
- .on("click dblclick", this.bind(function (e) {
- if (!this.isInterfaceEnabled()) return;
-
- $(e.target).closest(".select2-search-choice").fadeOut('fast', this.bind(function(){
- this.unselect($(e.target));
- this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
- this.close();
- this.focusSearch();
- })).dequeue();
- killEvent(e);
- })).on("focus", this.bind(function () {
- if (!this.isInterfaceEnabled()) return;
- this.container.addClass("select2-container-active");
- this.dropdown.addClass("select2-drop-active");
- }));
- }
-
- choice.data("select2-data", data);
- choice.insertBefore(this.searchContainer);
-
- val.push(id);
- this.setVal(val);
- },
-
- // multi
- unselect: function (selected) {
- var val = this.getVal(),
- data,
- index;
- selected = selected.closest(".select2-search-choice");
-
- if (selected.length === 0) {
- throw "Invalid argument: " + selected + ". Must be .select2-search-choice";
- }
-
- data = selected.data("select2-data");
-
- if (!data) {
- // prevent a race condition when the 'x' is clicked really fast repeatedly the event can be queued
- // and invoked on an element already removed
- return;
- }
-
- while((index = indexOf(this.id(data), val)) >= 0) {
- val.splice(index, 1);
- this.setVal(val);
- if (this.select) this.postprocessResults();
- }
-
- var evt = $.Event("select2-removing");
- evt.val = this.id(data);
- evt.choice = data;
- this.opts.element.trigger(evt);
-
- if (evt.isDefaultPrevented()) {
- return;
- }
-
- selected.remove();
-
- this.opts.element.trigger({ type: "select2-removed", val: this.id(data), choice: data });
- this.triggerChange({ removed: data });
- },
-
- // multi
- postprocessResults: function (data, initial, noHighlightUpdate) {
- var val = this.getVal(),
- choices = this.results.find(".select2-result"),
- compound = this.results.find(".select2-result-with-children"),
- self = this;
-
- choices.each2(function (i, choice) {
- var id = self.id(choice.data("select2-data"));
- if (indexOf(id, val) >= 0) {
- // By default, the selected item is hidden from the result list inside a multi select
- // User can provide an implementation for 'hideSelectionFromResult' and allow the same
- // element to be selected multiple times.
- if(self.opts.hideSelectionFromResult(choice) === undefined || self.opts.hideSelectionFromResult(choice)) {
- choice.addClass("select2-selected");
- // mark all children of the selected parent as selected
- choice.find(".select2-result-selectable").addClass("select2-selected");
- }
- }
- });
-
- compound.each2(function(i, choice) {
- // hide an optgroup if it doesn't have any selectable children
- if (!choice.is('.select2-result-selectable')
- && choice.find(".select2-result-selectable:not(.select2-selected)").length === 0) {
- choice.addClass("select2-selected");
- }
- });
-
- if (this.highlight() == -1 && noHighlightUpdate !== false){
- self.highlight(0);
- }
-
- //If all results are chosen render formatNoMatches
- if(!this.opts.createSearchChoice && !choices.filter('.select2-result:not(.select2-selected)').length > 0){
- if(!data || data && !data.more && this.results.find(".select2-no-results").length === 0) {
- if (checkFormatter(self.opts.formatNoMatches, "formatNoMatches")) {
- this.results.append("<li class='select2-no-results'>" + evaluate(self.opts.formatNoMatches, self.search.val()) + "</li>");
- }
- }
- }
-
- },
-
- // multi
- getMaxSearchWidth: function() {
- return this.selection.width() - getSideBorderPadding(this.search);
- },
-
- // multi
- resizeSearch: function () {
- var minimumWidth, left, maxWidth, containerLeft, searchWidth,
- sideBorderPadding = getSideBorderPadding(this.search);
-
- minimumWidth = measureTextWidth(this.search) + 10;
-
- left = this.search.offset().left;
-
- maxWidth = this.selection.width();
- containerLeft = this.selection.offset().left;
-
- searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding;
-
- if (searchWidth < minimumWidth) {
- searchWidth = maxWidth - sideBorderPadding;
- }
-
- if (searchWidth < 40) {
- searchWidth = maxWidth - sideBorderPadding;
- }
-
- if (searchWidth <= 0) {
- searchWidth = minimumWidth;
- }
-
- this.search.width(Math.floor(searchWidth));
- },
-
- // multi
- getVal: function () {
- var val;
- if (this.select) {
- val = this.select.val();
- return val === null ? [] : val;
- } else {
- val = this.opts.element.val();
- return splitVal(val, this.opts.separator);
- }
- },
-
- // multi
- setVal: function (val) {
- var unique;
- if (this.select) {
- this.select.val(val);
- } else {
- unique = [];
- // filter out duplicates
- $(val).each(function () {
- if (indexOf(this, unique) < 0) unique.push(this);
- });
- this.opts.element.val(unique.length === 0 ? "" : unique.join(this.opts.separator));
- }
- },
-
- // multi
- buildChangeDetails: function (old, current) {
- var current = current.slice(0),
- old = old.slice(0);
-
- // remove intersection from each array
- for (var i = 0; i < current.length; i++) {
- for (var j = 0; j < old.length; j++) {
- if (equal(this.opts.id(current[i]), this.opts.id(old[j]))) {
- current.splice(i, 1);
- if(i>0){
- i--;
- }
- old.splice(j, 1);
- j--;
- }
- }
- }
-
- return {added: current, removed: old};
- },
-
-
- // multi
- val: function (val, triggerChange) {
- var oldData, self=this;
-
- if (arguments.length === 0) {
- return this.getVal();
- }
-
- oldData=this.data();
- if (!oldData.length) oldData=[];
-
- // val is an id. !val is true for [undefined,null,'',0] - 0 is legal
- if (!val && val !== 0) {
- this.opts.element.val("");
- this.updateSelection([]);
- this.clearSearch();
- if (triggerChange) {
- this.triggerChange({added: this.data(), removed: oldData});
- }
- return;
- }
-
- // val is a list of ids
- this.setVal(val);
-
- if (this.select) {
- this.opts.initSelection(this.select, this.bind(this.updateSelection));
- if (triggerChange) {
- this.triggerChange(this.buildChangeDetails(oldData, this.data()));
- }
- } else {
- if (this.opts.initSelection === undefined) {
- throw new Error("val() cannot be called if initSelection() is not defined");
- }
-
- this.opts.initSelection(this.opts.element, function(data){
- var ids=$.map(data, self.id);
- self.setVal(ids);
- self.updateSelection(data);
- self.clearSearch();
- if (triggerChange) {
- self.triggerChange(self.buildChangeDetails(oldData, self.data()));
- }
- });
- }
- this.clearSearch();
- },
-
- // multi
- onSortStart: function() {
- if (this.select) {
- throw new Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead.");
- }
-
- // collapse search field into 0 width so its container can be collapsed as well
- this.search.width(0);
- // hide the container
- this.searchContainer.hide();
- },
-
- // multi
- onSortEnd:function() {
-
- var val=[], self=this;
-
- // show search and move it to the end of the list
- this.searchContainer.show();
- // make sure the search container is the last item in the list
- this.searchContainer.appendTo(this.searchContainer.parent());
- // since we collapsed the width in dragStarted, we resize it here
- this.resizeSearch();
-
- // update selection
- this.selection.find(".select2-search-choice").each(function() {
- val.push(self.opts.id($(this).data("select2-data")));
- });
- this.setVal(val);
- this.triggerChange();
- },
-
- // multi
- data: function(values, triggerChange) {
- var self=this, ids, old;
- if (arguments.length === 0) {
- return this.selection
- .children(".select2-search-choice")
- .map(function() { return $(this).data("select2-data"); })
- .get();
- } else {
- old = this.data();
- if (!values) { values = []; }
- ids = $.map(values, function(e) { return self.opts.id(e); });
- this.setVal(ids);
- this.updateSelection(values);
- this.clearSearch();
- if (triggerChange) {
- this.triggerChange(this.buildChangeDetails(old, this.data()));
- }
- }
- }
- });
-
- $.fn.select2 = function () {
-
- var args = Array.prototype.slice.call(arguments, 0),
- opts,
- select2,
- method, value, multiple,
- allowedMethods = ["val", "destroy", "opened", "open", "close", "focus", "isFocused", "container", "dropdown", "onSortStart", "onSortEnd", "enable", "disable", "readonly", "positionDropdown", "data", "search"],
- valueMethods = ["opened", "isFocused", "container", "dropdown"],
- propertyMethods = ["val", "data"],
- methodsMap = { search: "externalSearch" };
-
- this.each(function () {
- if (args.length === 0 || typeof(args[0]) === "object") {
- opts = args.length === 0 ? {} : $.extend({}, args[0]);
- opts.element = $(this);
-
- if (opts.element.get(0).tagName.toLowerCase() === "select") {
- multiple = opts.element.prop("multiple");
- } else {
- multiple = opts.multiple || false;
- if ("tags" in opts) {opts.multiple = multiple = true;}
- }
-
- select2 = multiple ? new window.Select2["class"].multi() : new window.Select2["class"].single();
- select2.init(opts);
- } else if (typeof(args[0]) === "string") {
-
- if (indexOf(args[0], allowedMethods) < 0) {
- throw "Unknown method: " + args[0];
- }
-
- value = undefined;
- select2 = $(this).data("select2");
- if (select2 === undefined) return;
-
- method=args[0];
-
- if (method === "container") {
- value = select2.container;
- } else if (method === "dropdown") {
- value = select2.dropdown;
- } else {
- if (methodsMap[method]) method = methodsMap[method];
-
- value = select2[method].apply(select2, args.slice(1));
- }
- if (indexOf(args[0], valueMethods) >= 0
- || (indexOf(args[0], propertyMethods) && args.length == 1)) {
- return false; // abort the iteration, ready to return first matched value
- }
- } else {
- throw "Invalid arguments to select2 plugin: " + args;
- }
- });
- return (value === undefined) ? this : value;
- };
-
- // plugin defaults, accessible to users
- $.fn.select2.defaults = {
- width: "copy",
- loadMorePadding: 0,
- closeOnSelect: true,
- openOnEnter: true,
- containerCss: {},
- dropdownCss: {},
- containerCssClass: "",
- dropdownCssClass: "",
- formatResult: function(result, container, query, escapeMarkup) {
- var markup=[];
- markMatch(result.text, query.term, markup, escapeMarkup);
- return markup.join("");
- },
- formatSelection: function (data, container, escapeMarkup) {
- return data ? escapeMarkup(data.text) : undefined;
- },
- sortResults: function (results, container, query) {
- return results;
- },
- formatResultCssClass: function(data) {return data.css;},
- formatSelectionCssClass: function(data, container) {return undefined;},
- formatMatches: function (matches) { return matches + " results are available, use up and down arrow keys to navigate."; },
- formatNoMatches: function () { return "No matches found"; },
- formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " or more character" + (n == 1? "" : "s"); },
- formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1? "" : "s"); },
- formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); },
- formatLoadMore: function (pageNumber) { return "Loading more results…"; },
- formatSearching: function () { return "Searching…"; },
- minimumResultsForSearch: 0,
- minimumInputLength: 0,
- maximumInputLength: null,
- maximumSelectionSize: 0,
- id: function (e) { return e == undefined ? null : e.id; },
- matcher: function(term, text) {
- return stripDiacritics(''+text).toUpperCase().indexOf(stripDiacritics(''+term).toUpperCase()) >= 0;
- },
- separator: ",",
- tokenSeparators: [],
- tokenizer: defaultTokenizer,
- escapeMarkup: defaultEscapeMarkup,
- blurOnChange: false,
- selectOnBlur: false,
- adaptContainerCssClass: function(c) { return c; },
- adaptDropdownCssClass: function(c) { return null; },
- nextSearchTerm: function(selectedObject, currentSearchTerm) { return undefined; },
- hideSelectionFromResult: function(selectedObject) { return undefined; },
- searchInputPlaceholder: '',
- createSearchChoicePosition: 'top'
- };
-
- $.fn.select2.ajaxDefaults = {
- transport: $.ajax,
- params: {
- type: "GET",
- cache: false,
- dataType: "json"
- }
- };
-
- // exports
- window.Select2 = {
- query: {
- ajax: ajax,
- local: local,
- tags: tags
- }, util: {
- debounce: debounce,
- markMatch: markMatch,
- escapeMarkup: defaultEscapeMarkup,
- stripDiacritics: stripDiacritics
- }, "class": {
- "abstract": AbstractSelect2,
- "single": SingleSelect2,
- "multi": MultiSelect2
- }
- };
-
-}(jQuery));