Merge lp:~raoul-snyman/openlp/upgrade-jquery-2.4 into lp:openlp/2.4

Proposed by Raoul Snyman
Status: Merged
Merged at revision: 2662
Proposed branch: lp:~raoul-snyman/openlp/upgrade-jquery-2.4
Merge into: lp:openlp/2.4
Diff against target: 922 lines (+824/-35)
5 files modified
openlp/plugins/remotes/html/index.html (+12/-11)
openlp/plugins/remotes/html/jquery-migrate.js (+752/-0)
openlp/plugins/remotes/html/jquery-migrate.min.js (+2/-0)
openlp/plugins/remotes/html/openlp.js (+26/-24)
tests/interfaces/openlp_core_ui/test_shortcutlistform.py (+32/-0)
To merge this branch: bzr merge lp:~raoul-snyman/openlp/upgrade-jquery-2.4
Reviewer Review Type Date Requested Status
Tim Bentley Approve
Tomas Groth Pending
Review via email: mp+313387@code.launchpad.net

This proposal supersedes a proposal from 2016-12-14.

To post a comment you must log in.
Revision history for this message
Tomas Groth (tomasgroth) wrote : Posted in a previous version of this proposal

"Once and for all" are rather big words ;)

review: Approve
Revision history for this message
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal

Should we have console.log code here

review: Needs Fixing
Revision history for this message
Tim Bentley (trb143) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/plugins/remotes/html/index.html'
2--- openlp/plugins/remotes/html/index.html 2016-01-10 16:00:05 +0000
3+++ openlp/plugins/remotes/html/index.html 2016-12-15 18:14:46 +0000
4@@ -27,17 +27,6 @@
5 <link rel="stylesheet" href="/files/jquery.mobile.min.css" />
6 <link rel="stylesheet" href="/files/openlp.css" />
7 <link rel="shortcut icon" type="image/x-icon" href="/files/images/favicon.ico">
8- <script type="text/javascript" src="/files/jquery.min.js"></script>
9- <script type="text/javascript" src="/files/openlp.js"></script>
10- <script type="text/javascript" src="/files/jquery.mobile.min.js"></script>
11- <script type="text/javascript">
12- translationStrings = {
13- "go_live": "${go_live}",
14- "add_to_service": "${add_to_service}",
15- "no_results": "${no_results}",
16- "home": "${home}"
17- }
18- </script>
19 </head>
20 <body>
21 <div data-role="page" id="home">
22@@ -173,5 +162,17 @@
23 <a href="#" id="add-and-go-to-service" data-role="button">${add_and_go_to_service}</a>
24 </div>
25 </div>
26+<script type="text/javascript" src="/files/jquery.min.js"></script>
27+<script type="text/javascript" src="/files/jquery-migrate.min.js"></script>
28+<script type="text/javascript" src="/files/jquery.mobile.min.js"></script>
29+<script type="text/javascript" src="/files/openlp.js"></script>
30+<script type="text/javascript">
31+translationStrings = {
32+ "go_live": "${go_live}",
33+ "add_to_service": "${add_to_service}",
34+ "no_results": "${no_results}",
35+ "home": "${home}"
36+};
37+</script>
38 </body>
39 </html>
40
41=== added file 'openlp/plugins/remotes/html/jquery-migrate.js'
42--- openlp/plugins/remotes/html/jquery-migrate.js 1970-01-01 00:00:00 +0000
43+++ openlp/plugins/remotes/html/jquery-migrate.js 2016-12-15 18:14:46 +0000
44@@ -0,0 +1,752 @@
45+/*!
46+ * jQuery Migrate - v1.4.1 - 2016-05-19
47+ * Copyright jQuery Foundation and other contributors
48+ */
49+(function( jQuery, window, undefined ) {
50+// See http://bugs.jquery.com/ticket/13335
51+// "use strict";
52+
53+
54+jQuery.migrateVersion = "1.4.1";
55+
56+
57+var warnedAbout = {};
58+
59+// List of warnings already given; public read only
60+jQuery.migrateWarnings = [];
61+
62+// Set to true to prevent console output; migrateWarnings still maintained
63+// jQuery.migrateMute = false;
64+
65+// Show a message on the console so devs know we're active
66+if ( window.console && window.console.log ) {
67+ window.console.log( "JQMIGRATE: Migrate is installed" +
68+ ( jQuery.migrateMute ? "" : " with logging active" ) +
69+ ", version " + jQuery.migrateVersion );
70+}
71+
72+// Set to false to disable traces that appear with warnings
73+if ( jQuery.migrateTrace === undefined ) {
74+ jQuery.migrateTrace = true;
75+}
76+
77+// Forget any warnings we've already given; public
78+jQuery.migrateReset = function() {
79+ warnedAbout = {};
80+ jQuery.migrateWarnings.length = 0;
81+};
82+
83+function migrateWarn( msg) {
84+ var console = window.console;
85+ if ( !warnedAbout[ msg ] ) {
86+ warnedAbout[ msg ] = true;
87+ jQuery.migrateWarnings.push( msg );
88+ if ( console && console.warn && !jQuery.migrateMute ) {
89+ console.warn( "JQMIGRATE: " + msg );
90+ if ( jQuery.migrateTrace && console.trace ) {
91+ console.trace();
92+ }
93+ }
94+ }
95+}
96+
97+function migrateWarnProp( obj, prop, value, msg ) {
98+ if ( Object.defineProperty ) {
99+ // On ES5 browsers (non-oldIE), warn if the code tries to get prop;
100+ // allow property to be overwritten in case some other plugin wants it
101+ try {
102+ Object.defineProperty( obj, prop, {
103+ configurable: true,
104+ enumerable: true,
105+ get: function() {
106+ migrateWarn( msg );
107+ return value;
108+ },
109+ set: function( newValue ) {
110+ migrateWarn( msg );
111+ value = newValue;
112+ }
113+ });
114+ return;
115+ } catch( err ) {
116+ // IE8 is a dope about Object.defineProperty, can't warn there
117+ }
118+ }
119+
120+ // Non-ES5 (or broken) browser; just set the property
121+ jQuery._definePropertyBroken = true;
122+ obj[ prop ] = value;
123+}
124+
125+if ( document.compatMode === "BackCompat" ) {
126+ // jQuery has never supported or tested Quirks Mode
127+ migrateWarn( "jQuery is not compatible with Quirks Mode" );
128+}
129+
130+
131+var attrFn = jQuery( "<input/>", { size: 1 } ).attr("size") && jQuery.attrFn,
132+ oldAttr = jQuery.attr,
133+ valueAttrGet = jQuery.attrHooks.value && jQuery.attrHooks.value.get ||
134+ function() { return null; },
135+ valueAttrSet = jQuery.attrHooks.value && jQuery.attrHooks.value.set ||
136+ function() { return undefined; },
137+ rnoType = /^(?:input|button)$/i,
138+ rnoAttrNodeType = /^[238]$/,
139+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
140+ ruseDefault = /^(?:checked|selected)$/i;
141+
142+// jQuery.attrFn
143+migrateWarnProp( jQuery, "attrFn", attrFn || {}, "jQuery.attrFn is deprecated" );
144+
145+jQuery.attr = function( elem, name, value, pass ) {
146+ var lowerName = name.toLowerCase(),
147+ nType = elem && elem.nodeType;
148+
149+ if ( pass ) {
150+ // Since pass is used internally, we only warn for new jQuery
151+ // versions where there isn't a pass arg in the formal params
152+ if ( oldAttr.length < 4 ) {
153+ migrateWarn("jQuery.fn.attr( props, pass ) is deprecated");
154+ }
155+ if ( elem && !rnoAttrNodeType.test( nType ) &&
156+ (attrFn ? name in attrFn : jQuery.isFunction(jQuery.fn[name])) ) {
157+ return jQuery( elem )[ name ]( value );
158+ }
159+ }
160+
161+ // Warn if user tries to set `type`, since it breaks on IE 6/7/8; by checking
162+ // for disconnected elements we don't warn on $( "<button>", { type: "button" } ).
163+ if ( name === "type" && value !== undefined && rnoType.test( elem.nodeName ) && elem.parentNode ) {
164+ migrateWarn("Can't change the 'type' of an input or button in IE 6/7/8");
165+ }
166+
167+ // Restore boolHook for boolean property/attribute synchronization
168+ if ( !jQuery.attrHooks[ lowerName ] && rboolean.test( lowerName ) ) {
169+ jQuery.attrHooks[ lowerName ] = {
170+ get: function( elem, name ) {
171+ // Align boolean attributes with corresponding properties
172+ // Fall back to attribute presence where some booleans are not supported
173+ var attrNode,
174+ property = jQuery.prop( elem, name );
175+ return property === true || typeof property !== "boolean" &&
176+ ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
177+
178+ name.toLowerCase() :
179+ undefined;
180+ },
181+ set: function( elem, value, name ) {
182+ var propName;
183+ if ( value === false ) {
184+ // Remove boolean attributes when set to false
185+ jQuery.removeAttr( elem, name );
186+ } else {
187+ // value is true since we know at this point it's type boolean and not false
188+ // Set boolean attributes to the same name and set the DOM property
189+ propName = jQuery.propFix[ name ] || name;
190+ if ( propName in elem ) {
191+ // Only set the IDL specifically if it already exists on the element
192+ elem[ propName ] = true;
193+ }
194+
195+ elem.setAttribute( name, name.toLowerCase() );
196+ }
197+ return name;
198+ }
199+ };
200+
201+ // Warn only for attributes that can remain distinct from their properties post-1.9
202+ if ( ruseDefault.test( lowerName ) ) {
203+ migrateWarn( "jQuery.fn.attr('" + lowerName + "') might use property instead of attribute" );
204+ }
205+ }
206+
207+ return oldAttr.call( jQuery, elem, name, value );
208+};
209+
210+// attrHooks: value
211+jQuery.attrHooks.value = {
212+ get: function( elem, name ) {
213+ var nodeName = ( elem.nodeName || "" ).toLowerCase();
214+ if ( nodeName === "button" ) {
215+ return valueAttrGet.apply( this, arguments );
216+ }
217+ if ( nodeName !== "input" && nodeName !== "option" ) {
218+ migrateWarn("jQuery.fn.attr('value') no longer gets properties");
219+ }
220+ return name in elem ?
221+ elem.value :
222+ null;
223+ },
224+ set: function( elem, value ) {
225+ var nodeName = ( elem.nodeName || "" ).toLowerCase();
226+ if ( nodeName === "button" ) {
227+ return valueAttrSet.apply( this, arguments );
228+ }
229+ if ( nodeName !== "input" && nodeName !== "option" ) {
230+ migrateWarn("jQuery.fn.attr('value', val) no longer sets properties");
231+ }
232+ // Does not return so that setAttribute is also used
233+ elem.value = value;
234+ }
235+};
236+
237+
238+var matched, browser,
239+ oldInit = jQuery.fn.init,
240+ oldFind = jQuery.find,
241+ oldParseJSON = jQuery.parseJSON,
242+ rspaceAngle = /^\s*</,
243+ rattrHashTest = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/,
244+ rattrHashGlob = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g,
245+ // Note: XSS check is done below after string is trimmed
246+ rquickExpr = /^([^<]*)(<[\w\W]+>)([^>]*)$/;
247+
248+// $(html) "looks like html" rule change
249+jQuery.fn.init = function( selector, context, rootjQuery ) {
250+ var match, ret;
251+
252+ if ( selector && typeof selector === "string" ) {
253+ if ( !jQuery.isPlainObject( context ) &&
254+ (match = rquickExpr.exec( jQuery.trim( selector ) )) && match[ 0 ] ) {
255+
256+ // This is an HTML string according to the "old" rules; is it still?
257+ if ( !rspaceAngle.test( selector ) ) {
258+ migrateWarn("$(html) HTML strings must start with '<' character");
259+ }
260+ if ( match[ 3 ] ) {
261+ migrateWarn("$(html) HTML text after last tag is ignored");
262+ }
263+
264+ // Consistently reject any HTML-like string starting with a hash (gh-9521)
265+ // Note that this may break jQuery 1.6.x code that otherwise would work.
266+ if ( match[ 0 ].charAt( 0 ) === "#" ) {
267+ migrateWarn("HTML string cannot start with a '#' character");
268+ jQuery.error("JQMIGRATE: Invalid selector string (XSS)");
269+ }
270+
271+ // Now process using loose rules; let pre-1.8 play too
272+ // Is this a jQuery context? parseHTML expects a DOM element (#178)
273+ if ( context && context.context && context.context.nodeType ) {
274+ context = context.context;
275+ }
276+
277+ if ( jQuery.parseHTML ) {
278+ return oldInit.call( this,
279+ jQuery.parseHTML( match[ 2 ], context && context.ownerDocument ||
280+ context || document, true ), context, rootjQuery );
281+ }
282+ }
283+ }
284+
285+ ret = oldInit.apply( this, arguments );
286+
287+ // Fill in selector and context properties so .live() works
288+ if ( selector && selector.selector !== undefined ) {
289+ // A jQuery object, copy its properties
290+ ret.selector = selector.selector;
291+ ret.context = selector.context;
292+
293+ } else {
294+ ret.selector = typeof selector === "string" ? selector : "";
295+ if ( selector ) {
296+ ret.context = selector.nodeType? selector : context || document;
297+ }
298+ }
299+
300+ return ret;
301+};
302+jQuery.fn.init.prototype = jQuery.fn;
303+
304+jQuery.find = function( selector ) {
305+ var args = Array.prototype.slice.call( arguments );
306+
307+ // Support: PhantomJS 1.x
308+ // String#match fails to match when used with a //g RegExp, only on some strings
309+ if ( typeof selector === "string" && rattrHashTest.test( selector ) ) {
310+
311+ // The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0
312+ // First see if qS thinks it's a valid selector, if so avoid a false positive
313+ try {
314+ document.querySelector( selector );
315+ } catch ( err1 ) {
316+
317+ // Didn't *look* valid to qSA, warn and try quoting what we think is the value
318+ selector = selector.replace( rattrHashGlob, function( _, attr, op, value ) {
319+ return "[" + attr + op + "\"" + value + "\"]";
320+ } );
321+
322+ // If the regexp *may* have created an invalid selector, don't update it
323+ // Note that there may be false alarms if selector uses jQuery extensions
324+ try {
325+ document.querySelector( selector );
326+ migrateWarn( "Attribute selector with '#' must be quoted: " + args[ 0 ] );
327+ args[ 0 ] = selector;
328+ } catch ( err2 ) {
329+ migrateWarn( "Attribute selector with '#' was not fixed: " + args[ 0 ] );
330+ }
331+ }
332+ }
333+
334+ return oldFind.apply( this, args );
335+};
336+
337+// Copy properties attached to original jQuery.find method (e.g. .attr, .isXML)
338+var findProp;
339+for ( findProp in oldFind ) {
340+ if ( Object.prototype.hasOwnProperty.call( oldFind, findProp ) ) {
341+ jQuery.find[ findProp ] = oldFind[ findProp ];
342+ }
343+}
344+
345+// Let $.parseJSON(falsy_value) return null
346+jQuery.parseJSON = function( json ) {
347+ if ( !json ) {
348+ migrateWarn("jQuery.parseJSON requires a valid JSON string");
349+ return null;
350+ }
351+ return oldParseJSON.apply( this, arguments );
352+};
353+
354+jQuery.uaMatch = function( ua ) {
355+ ua = ua.toLowerCase();
356+
357+ var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
358+ /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
359+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
360+ /(msie) ([\w.]+)/.exec( ua ) ||
361+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
362+ [];
363+
364+ return {
365+ browser: match[ 1 ] || "",
366+ version: match[ 2 ] || "0"
367+ };
368+};
369+
370+// Don't clobber any existing jQuery.browser in case it's different
371+if ( !jQuery.browser ) {
372+ matched = jQuery.uaMatch( navigator.userAgent );
373+ browser = {};
374+
375+ if ( matched.browser ) {
376+ browser[ matched.browser ] = true;
377+ browser.version = matched.version;
378+ }
379+
380+ // Chrome is Webkit, but Webkit is also Safari.
381+ if ( browser.chrome ) {
382+ browser.webkit = true;
383+ } else if ( browser.webkit ) {
384+ browser.safari = true;
385+ }
386+
387+ jQuery.browser = browser;
388+}
389+
390+// Warn if the code tries to get jQuery.browser
391+migrateWarnProp( jQuery, "browser", jQuery.browser, "jQuery.browser is deprecated" );
392+
393+// jQuery.boxModel deprecated in 1.3, jQuery.support.boxModel deprecated in 1.7
394+jQuery.boxModel = jQuery.support.boxModel = (document.compatMode === "CSS1Compat");
395+migrateWarnProp( jQuery, "boxModel", jQuery.boxModel, "jQuery.boxModel is deprecated" );
396+migrateWarnProp( jQuery.support, "boxModel", jQuery.support.boxModel, "jQuery.support.boxModel is deprecated" );
397+
398+jQuery.sub = function() {
399+ function jQuerySub( selector, context ) {
400+ return new jQuerySub.fn.init( selector, context );
401+ }
402+ jQuery.extend( true, jQuerySub, this );
403+ jQuerySub.superclass = this;
404+ jQuerySub.fn = jQuerySub.prototype = this();
405+ jQuerySub.fn.constructor = jQuerySub;
406+ jQuerySub.sub = this.sub;
407+ jQuerySub.fn.init = function init( selector, context ) {
408+ var instance = jQuery.fn.init.call( this, selector, context, rootjQuerySub );
409+ return instance instanceof jQuerySub ?
410+ instance :
411+ jQuerySub( instance );
412+ };
413+ jQuerySub.fn.init.prototype = jQuerySub.fn;
414+ var rootjQuerySub = jQuerySub(document);
415+ migrateWarn( "jQuery.sub() is deprecated" );
416+ return jQuerySub;
417+};
418+
419+// The number of elements contained in the matched element set
420+jQuery.fn.size = function() {
421+ migrateWarn( "jQuery.fn.size() is deprecated; use the .length property" );
422+ return this.length;
423+};
424+
425+
426+var internalSwapCall = false;
427+
428+// If this version of jQuery has .swap(), don't false-alarm on internal uses
429+if ( jQuery.swap ) {
430+ jQuery.each( [ "height", "width", "reliableMarginRight" ], function( _, name ) {
431+ var oldHook = jQuery.cssHooks[ name ] && jQuery.cssHooks[ name ].get;
432+
433+ if ( oldHook ) {
434+ jQuery.cssHooks[ name ].get = function() {
435+ var ret;
436+
437+ internalSwapCall = true;
438+ ret = oldHook.apply( this, arguments );
439+ internalSwapCall = false;
440+ return ret;
441+ };
442+ }
443+ });
444+}
445+
446+jQuery.swap = function( elem, options, callback, args ) {
447+ var ret, name,
448+ old = {};
449+
450+ if ( !internalSwapCall ) {
451+ migrateWarn( "jQuery.swap() is undocumented and deprecated" );
452+ }
453+
454+ // Remember the old values, and insert the new ones
455+ for ( name in options ) {
456+ old[ name ] = elem.style[ name ];
457+ elem.style[ name ] = options[ name ];
458+ }
459+
460+ ret = callback.apply( elem, args || [] );
461+
462+ // Revert the old values
463+ for ( name in options ) {
464+ elem.style[ name ] = old[ name ];
465+ }
466+
467+ return ret;
468+};
469+
470+
471+// Ensure that $.ajax gets the new parseJSON defined in core.js
472+jQuery.ajaxSetup({
473+ converters: {
474+ "text json": jQuery.parseJSON
475+ }
476+});
477+
478+
479+var oldFnData = jQuery.fn.data;
480+
481+jQuery.fn.data = function( name ) {
482+ var ret, evt,
483+ elem = this[0];
484+
485+ // Handles 1.7 which has this behavior and 1.8 which doesn't
486+ if ( elem && name === "events" && arguments.length === 1 ) {
487+ ret = jQuery.data( elem, name );
488+ evt = jQuery._data( elem, name );
489+ if ( ( ret === undefined || ret === evt ) && evt !== undefined ) {
490+ migrateWarn("Use of jQuery.fn.data('events') is deprecated");
491+ return evt;
492+ }
493+ }
494+ return oldFnData.apply( this, arguments );
495+};
496+
497+
498+var rscriptType = /\/(java|ecma)script/i;
499+
500+// Since jQuery.clean is used internally on older versions, we only shim if it's missing
501+if ( !jQuery.clean ) {
502+ jQuery.clean = function( elems, context, fragment, scripts ) {
503+ // Set context per 1.8 logic
504+ context = context || document;
505+ context = !context.nodeType && context[0] || context;
506+ context = context.ownerDocument || context;
507+
508+ migrateWarn("jQuery.clean() is deprecated");
509+
510+ var i, elem, handleScript, jsTags,
511+ ret = [];
512+
513+ jQuery.merge( ret, jQuery.buildFragment( elems, context ).childNodes );
514+
515+ // Complex logic lifted directly from jQuery 1.8
516+ if ( fragment ) {
517+ // Special handling of each script element
518+ handleScript = function( elem ) {
519+ // Check if we consider it executable
520+ if ( !elem.type || rscriptType.test( elem.type ) ) {
521+ // Detach the script and store it in the scripts array (if provided) or the fragment
522+ // Return truthy to indicate that it has been handled
523+ return scripts ?
524+ scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
525+ fragment.appendChild( elem );
526+ }
527+ };
528+
529+ for ( i = 0; (elem = ret[i]) != null; i++ ) {
530+ // Check if we're done after handling an executable script
531+ if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
532+ // Append to fragment and handle embedded scripts
533+ fragment.appendChild( elem );
534+ if ( typeof elem.getElementsByTagName !== "undefined" ) {
535+ // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
536+ jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
537+
538+ // Splice the scripts into ret after their former ancestor and advance our index beyond them
539+ ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
540+ i += jsTags.length;
541+ }
542+ }
543+ }
544+ }
545+
546+ return ret;
547+ };
548+}
549+
550+var eventAdd = jQuery.event.add,
551+ eventRemove = jQuery.event.remove,
552+ eventTrigger = jQuery.event.trigger,
553+ oldToggle = jQuery.fn.toggle,
554+ oldLive = jQuery.fn.live,
555+ oldDie = jQuery.fn.die,
556+ oldLoad = jQuery.fn.load,
557+ ajaxEvents = "ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",
558+ rajaxEvent = new RegExp( "\\b(?:" + ajaxEvents + ")\\b" ),
559+ rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
560+ hoverHack = function( events ) {
561+ if ( typeof( events ) !== "string" || jQuery.event.special.hover ) {
562+ return events;
563+ }
564+ if ( rhoverHack.test( events ) ) {
565+ migrateWarn("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'");
566+ }
567+ return events && events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
568+ };
569+
570+// Event props removed in 1.9, put them back if needed; no practical way to warn them
571+if ( jQuery.event.props && jQuery.event.props[ 0 ] !== "attrChange" ) {
572+ jQuery.event.props.unshift( "attrChange", "attrName", "relatedNode", "srcElement" );
573+}
574+
575+// Undocumented jQuery.event.handle was "deprecated" in jQuery 1.7
576+if ( jQuery.event.dispatch ) {
577+ migrateWarnProp( jQuery.event, "handle", jQuery.event.dispatch, "jQuery.event.handle is undocumented and deprecated" );
578+}
579+
580+// Support for 'hover' pseudo-event and ajax event warnings
581+jQuery.event.add = function( elem, types, handler, data, selector ){
582+ if ( elem !== document && rajaxEvent.test( types ) ) {
583+ migrateWarn( "AJAX events should be attached to document: " + types );
584+ }
585+ eventAdd.call( this, elem, hoverHack( types || "" ), handler, data, selector );
586+};
587+jQuery.event.remove = function( elem, types, handler, selector, mappedTypes ){
588+ eventRemove.call( this, elem, hoverHack( types ) || "", handler, selector, mappedTypes );
589+};
590+
591+jQuery.each( [ "load", "unload", "error" ], function( _, name ) {
592+
593+ jQuery.fn[ name ] = function() {
594+ var args = Array.prototype.slice.call( arguments, 0 );
595+
596+ // If this is an ajax load() the first arg should be the string URL;
597+ // technically this could also be the "Anything" arg of the event .load()
598+ // which just goes to show why this dumb signature has been deprecated!
599+ // jQuery custom builds that exclude the Ajax module justifiably die here.
600+ if ( name === "load" && typeof args[ 0 ] === "string" ) {
601+ return oldLoad.apply( this, args );
602+ }
603+
604+ migrateWarn( "jQuery.fn." + name + "() is deprecated" );
605+
606+ args.splice( 0, 0, name );
607+ if ( arguments.length ) {
608+ return this.bind.apply( this, args );
609+ }
610+
611+ // Use .triggerHandler here because:
612+ // - load and unload events don't need to bubble, only applied to window or image
613+ // - error event should not bubble to window, although it does pre-1.7
614+ // See http://bugs.jquery.com/ticket/11820
615+ this.triggerHandler.apply( this, args );
616+ return this;
617+ };
618+
619+});
620+
621+jQuery.fn.toggle = function( fn, fn2 ) {
622+
623+ // Don't mess with animation or css toggles
624+ if ( !jQuery.isFunction( fn ) || !jQuery.isFunction( fn2 ) ) {
625+ return oldToggle.apply( this, arguments );
626+ }
627+ migrateWarn("jQuery.fn.toggle(handler, handler...) is deprecated");
628+
629+ // Save reference to arguments for access in closure
630+ var args = arguments,
631+ guid = fn.guid || jQuery.guid++,
632+ i = 0,
633+ toggler = function( event ) {
634+ // Figure out which function to execute
635+ var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
636+ jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
637+
638+ // Make sure that clicks stop
639+ event.preventDefault();
640+
641+ // and execute the function
642+ return args[ lastToggle ].apply( this, arguments ) || false;
643+ };
644+
645+ // link all the functions, so any of them can unbind this click handler
646+ toggler.guid = guid;
647+ while ( i < args.length ) {
648+ args[ i++ ].guid = guid;
649+ }
650+
651+ return this.click( toggler );
652+};
653+
654+jQuery.fn.live = function( types, data, fn ) {
655+ migrateWarn("jQuery.fn.live() is deprecated");
656+ if ( oldLive ) {
657+ return oldLive.apply( this, arguments );
658+ }
659+ jQuery( this.context ).on( types, this.selector, data, fn );
660+ return this;
661+};
662+
663+jQuery.fn.die = function( types, fn ) {
664+ migrateWarn("jQuery.fn.die() is deprecated");
665+ if ( oldDie ) {
666+ return oldDie.apply( this, arguments );
667+ }
668+ jQuery( this.context ).off( types, this.selector || "**", fn );
669+ return this;
670+};
671+
672+// Turn global events into document-triggered events
673+jQuery.event.trigger = function( event, data, elem, onlyHandlers ){
674+ if ( !elem && !rajaxEvent.test( event ) ) {
675+ migrateWarn( "Global events are undocumented and deprecated" );
676+ }
677+ return eventTrigger.call( this, event, data, elem || document, onlyHandlers );
678+};
679+jQuery.each( ajaxEvents.split("|"),
680+ function( _, name ) {
681+ jQuery.event.special[ name ] = {
682+ setup: function() {
683+ var elem = this;
684+
685+ // The document needs no shimming; must be !== for oldIE
686+ if ( elem !== document ) {
687+ jQuery.event.add( document, name + "." + jQuery.guid, function() {
688+ jQuery.event.trigger( name, Array.prototype.slice.call( arguments, 1 ), elem, true );
689+ });
690+ jQuery._data( this, name, jQuery.guid++ );
691+ }
692+ return false;
693+ },
694+ teardown: function() {
695+ if ( this !== document ) {
696+ jQuery.event.remove( document, name + "." + jQuery._data( this, name ) );
697+ }
698+ return false;
699+ }
700+ };
701+ }
702+);
703+
704+jQuery.event.special.ready = {
705+ setup: function() {
706+ if ( this === document ) {
707+ migrateWarn( "'ready' event is deprecated" );
708+ }
709+ }
710+};
711+
712+var oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack,
713+ oldFnFind = jQuery.fn.find;
714+
715+jQuery.fn.andSelf = function() {
716+ migrateWarn("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()");
717+ return oldSelf.apply( this, arguments );
718+};
719+
720+jQuery.fn.find = function( selector ) {
721+ var ret = oldFnFind.apply( this, arguments );
722+ ret.context = this.context;
723+ ret.selector = this.selector ? this.selector + " " + selector : selector;
724+ return ret;
725+};
726+
727+
728+// jQuery 1.6 did not support Callbacks, do not warn there
729+if ( jQuery.Callbacks ) {
730+
731+ var oldDeferred = jQuery.Deferred,
732+ tuples = [
733+ // action, add listener, callbacks, .then handlers, final state
734+ [ "resolve", "done", jQuery.Callbacks("once memory"),
735+ jQuery.Callbacks("once memory"), "resolved" ],
736+ [ "reject", "fail", jQuery.Callbacks("once memory"),
737+ jQuery.Callbacks("once memory"), "rejected" ],
738+ [ "notify", "progress", jQuery.Callbacks("memory"),
739+ jQuery.Callbacks("memory") ]
740+ ];
741+
742+ jQuery.Deferred = function( func ) {
743+ var deferred = oldDeferred(),
744+ promise = deferred.promise();
745+
746+ deferred.pipe = promise.pipe = function( /* fnDone, fnFail, fnProgress */ ) {
747+ var fns = arguments;
748+
749+ migrateWarn( "deferred.pipe() is deprecated" );
750+
751+ return jQuery.Deferred(function( newDefer ) {
752+ jQuery.each( tuples, function( i, tuple ) {
753+ var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
754+ // deferred.done(function() { bind to newDefer or newDefer.resolve })
755+ // deferred.fail(function() { bind to newDefer or newDefer.reject })
756+ // deferred.progress(function() { bind to newDefer or newDefer.notify })
757+ deferred[ tuple[1] ](function() {
758+ var returned = fn && fn.apply( this, arguments );
759+ if ( returned && jQuery.isFunction( returned.promise ) ) {
760+ returned.promise()
761+ .done( newDefer.resolve )
762+ .fail( newDefer.reject )
763+ .progress( newDefer.notify );
764+ } else {
765+ newDefer[ tuple[ 0 ] + "With" ](
766+ this === promise ? newDefer.promise() : this,
767+ fn ? [ returned ] : arguments
768+ );
769+ }
770+ });
771+ });
772+ fns = null;
773+ }).promise();
774+
775+ };
776+
777+ deferred.isResolved = function() {
778+ migrateWarn( "deferred.isResolved is deprecated" );
779+ return deferred.state() === "resolved";
780+ };
781+
782+ deferred.isRejected = function() {
783+ migrateWarn( "deferred.isRejected is deprecated" );
784+ return deferred.state() === "rejected";
785+ };
786+
787+ if ( func ) {
788+ func.call( deferred, deferred );
789+ }
790+
791+ return deferred;
792+ };
793+
794+}
795+
796+})( jQuery, window );
797
798=== added file 'openlp/plugins/remotes/html/jquery-migrate.min.js'
799--- openlp/plugins/remotes/html/jquery-migrate.min.js 1970-01-01 00:00:00 +0000
800+++ openlp/plugins/remotes/html/jquery-migrate.min.js 2016-12-15 18:14:46 +0000
801@@ -0,0 +1,2 @@
802+/*! jQuery Migrate v1.4.1 | (c) jQuery Foundation and other contributors | jquery.org/license */
803+"undefined"==typeof jQuery.migrateMute&&(jQuery.migrateMute=!0),function(a,b,c){function d(c){var d=b.console;f[c]||(f[c]=!0,a.migrateWarnings.push(c),d&&d.warn&&!a.migrateMute&&(d.warn("JQMIGRATE: "+c),a.migrateTrace&&d.trace&&d.trace()))}function e(b,c,e,f){if(Object.defineProperty)try{return void Object.defineProperty(b,c,{configurable:!0,enumerable:!0,get:function(){return d(f),e},set:function(a){d(f),e=a}})}catch(g){}a._definePropertyBroken=!0,b[c]=e}a.migrateVersion="1.4.1";var f={};a.migrateWarnings=[],b.console&&b.console.log&&b.console.log("JQMIGRATE: Migrate is installed"+(a.migrateMute?"":" with logging active")+", version "+a.migrateVersion),a.migrateTrace===c&&(a.migrateTrace=!0),a.migrateReset=function(){f={},a.migrateWarnings.length=0},"BackCompat"===document.compatMode&&d("jQuery is not compatible with Quirks Mode");var g=a("<input/>",{size:1}).attr("size")&&a.attrFn,h=a.attr,i=a.attrHooks.value&&a.attrHooks.value.get||function(){return null},j=a.attrHooks.value&&a.attrHooks.value.set||function(){return c},k=/^(?:input|button)$/i,l=/^[238]$/,m=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,n=/^(?:checked|selected)$/i;e(a,"attrFn",g||{},"jQuery.attrFn is deprecated"),a.attr=function(b,e,f,i){var j=e.toLowerCase(),o=b&&b.nodeType;return i&&(h.length<4&&d("jQuery.fn.attr( props, pass ) is deprecated"),b&&!l.test(o)&&(g?e in g:a.isFunction(a.fn[e])))?a(b)[e](f):("type"===e&&f!==c&&k.test(b.nodeName)&&b.parentNode&&d("Can't change the 'type' of an input or button in IE 6/7/8"),!a.attrHooks[j]&&m.test(j)&&(a.attrHooks[j]={get:function(b,d){var e,f=a.prop(b,d);return f===!0||"boolean"!=typeof f&&(e=b.getAttributeNode(d))&&e.nodeValue!==!1?d.toLowerCase():c},set:function(b,c,d){var e;return c===!1?a.removeAttr(b,d):(e=a.propFix[d]||d,e in b&&(b[e]=!0),b.setAttribute(d,d.toLowerCase())),d}},n.test(j)&&d("jQuery.fn.attr('"+j+"') might use property instead of attribute")),h.call(a,b,e,f))},a.attrHooks.value={get:function(a,b){var c=(a.nodeName||"").toLowerCase();return"button"===c?i.apply(this,arguments):("input"!==c&&"option"!==c&&d("jQuery.fn.attr('value') no longer gets properties"),b in a?a.value:null)},set:function(a,b){var c=(a.nodeName||"").toLowerCase();return"button"===c?j.apply(this,arguments):("input"!==c&&"option"!==c&&d("jQuery.fn.attr('value', val) no longer sets properties"),void(a.value=b))}};var o,p,q=a.fn.init,r=a.find,s=a.parseJSON,t=/^\s*</,u=/\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/,v=/\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g,w=/^([^<]*)(<[\w\W]+>)([^>]*)$/;a.fn.init=function(b,e,f){var g,h;return b&&"string"==typeof b&&!a.isPlainObject(e)&&(g=w.exec(a.trim(b)))&&g[0]&&(t.test(b)||d("$(html) HTML strings must start with '<' character"),g[3]&&d("$(html) HTML text after last tag is ignored"),"#"===g[0].charAt(0)&&(d("HTML string cannot start with a '#' character"),a.error("JQMIGRATE: Invalid selector string (XSS)")),e&&e.context&&e.context.nodeType&&(e=e.context),a.parseHTML)?q.call(this,a.parseHTML(g[2],e&&e.ownerDocument||e||document,!0),e,f):(h=q.apply(this,arguments),b&&b.selector!==c?(h.selector=b.selector,h.context=b.context):(h.selector="string"==typeof b?b:"",b&&(h.context=b.nodeType?b:e||document)),h)},a.fn.init.prototype=a.fn,a.find=function(a){var b=Array.prototype.slice.call(arguments);if("string"==typeof a&&u.test(a))try{document.querySelector(a)}catch(c){a=a.replace(v,function(a,b,c,d){return"["+b+c+'"'+d+'"]'});try{document.querySelector(a),d("Attribute selector with '#' must be quoted: "+b[0]),b[0]=a}catch(e){d("Attribute selector with '#' was not fixed: "+b[0])}}return r.apply(this,b)};var x;for(x in r)Object.prototype.hasOwnProperty.call(r,x)&&(a.find[x]=r[x]);a.parseJSON=function(a){return a?s.apply(this,arguments):(d("jQuery.parseJSON requires a valid JSON string"),null)},a.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a.browser||(o=a.uaMatch(navigator.userAgent),p={},o.browser&&(p[o.browser]=!0,p.version=o.version),p.chrome?p.webkit=!0:p.webkit&&(p.safari=!0),a.browser=p),e(a,"browser",a.browser,"jQuery.browser is deprecated"),a.boxModel=a.support.boxModel="CSS1Compat"===document.compatMode,e(a,"boxModel",a.boxModel,"jQuery.boxModel is deprecated"),e(a.support,"boxModel",a.support.boxModel,"jQuery.support.boxModel is deprecated"),a.sub=function(){function b(a,c){return new b.fn.init(a,c)}a.extend(!0,b,this),b.superclass=this,b.fn=b.prototype=this(),b.fn.constructor=b,b.sub=this.sub,b.fn.init=function(d,e){var f=a.fn.init.call(this,d,e,c);return f instanceof b?f:b(f)},b.fn.init.prototype=b.fn;var c=b(document);return d("jQuery.sub() is deprecated"),b},a.fn.size=function(){return d("jQuery.fn.size() is deprecated; use the .length property"),this.length};var y=!1;a.swap&&a.each(["height","width","reliableMarginRight"],function(b,c){var d=a.cssHooks[c]&&a.cssHooks[c].get;d&&(a.cssHooks[c].get=function(){var a;return y=!0,a=d.apply(this,arguments),y=!1,a})}),a.swap=function(a,b,c,e){var f,g,h={};y||d("jQuery.swap() is undocumented and deprecated");for(g in b)h[g]=a.style[g],a.style[g]=b[g];f=c.apply(a,e||[]);for(g in b)a.style[g]=h[g];return f},a.ajaxSetup({converters:{"text json":a.parseJSON}});var z=a.fn.data;a.fn.data=function(b){var e,f,g=this[0];return!g||"events"!==b||1!==arguments.length||(e=a.data(g,b),f=a._data(g,b),e!==c&&e!==f||f===c)?z.apply(this,arguments):(d("Use of jQuery.fn.data('events') is deprecated"),f)};var A=/\/(java|ecma)script/i;a.clean||(a.clean=function(b,c,e,f){c=c||document,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,d("jQuery.clean() is deprecated");var g,h,i,j,k=[];if(a.merge(k,a.buildFragment(b,c).childNodes),e)for(i=function(a){return!a.type||A.test(a.type)?f?f.push(a.parentNode?a.parentNode.removeChild(a):a):e.appendChild(a):void 0},g=0;null!=(h=k[g]);g++)a.nodeName(h,"script")&&i(h)||(e.appendChild(h),"undefined"!=typeof h.getElementsByTagName&&(j=a.grep(a.merge([],h.getElementsByTagName("script")),i),k.splice.apply(k,[g+1,0].concat(j)),g+=j.length));return k});var B=a.event.add,C=a.event.remove,D=a.event.trigger,E=a.fn.toggle,F=a.fn.live,G=a.fn.die,H=a.fn.load,I="ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",J=new RegExp("\\b(?:"+I+")\\b"),K=/(?:^|\s)hover(\.\S+|)\b/,L=function(b){return"string"!=typeof b||a.event.special.hover?b:(K.test(b)&&d("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'"),b&&b.replace(K,"mouseenter$1 mouseleave$1"))};a.event.props&&"attrChange"!==a.event.props[0]&&a.event.props.unshift("attrChange","attrName","relatedNode","srcElement"),a.event.dispatch&&e(a.event,"handle",a.event.dispatch,"jQuery.event.handle is undocumented and deprecated"),a.event.add=function(a,b,c,e,f){a!==document&&J.test(b)&&d("AJAX events should be attached to document: "+b),B.call(this,a,L(b||""),c,e,f)},a.event.remove=function(a,b,c,d,e){C.call(this,a,L(b)||"",c,d,e)},a.each(["load","unload","error"],function(b,c){a.fn[c]=function(){var a=Array.prototype.slice.call(arguments,0);return"load"===c&&"string"==typeof a[0]?H.apply(this,a):(d("jQuery.fn."+c+"() is deprecated"),a.splice(0,0,c),arguments.length?this.bind.apply(this,a):(this.triggerHandler.apply(this,a),this))}}),a.fn.toggle=function(b,c){if(!a.isFunction(b)||!a.isFunction(c))return E.apply(this,arguments);d("jQuery.fn.toggle(handler, handler...) is deprecated");var e=arguments,f=b.guid||a.guid++,g=0,h=function(c){var d=(a._data(this,"lastToggle"+b.guid)||0)%g;return a._data(this,"lastToggle"+b.guid,d+1),c.preventDefault(),e[d].apply(this,arguments)||!1};for(h.guid=f;g<e.length;)e[g++].guid=f;return this.click(h)},a.fn.live=function(b,c,e){return d("jQuery.fn.live() is deprecated"),F?F.apply(this,arguments):(a(this.context).on(b,this.selector,c,e),this)},a.fn.die=function(b,c){return d("jQuery.fn.die() is deprecated"),G?G.apply(this,arguments):(a(this.context).off(b,this.selector||"**",c),this)},a.event.trigger=function(a,b,c,e){return c||J.test(a)||d("Global events are undocumented and deprecated"),D.call(this,a,b,c||document,e)},a.each(I.split("|"),function(b,c){a.event.special[c]={setup:function(){var b=this;return b!==document&&(a.event.add(document,c+"."+a.guid,function(){a.event.trigger(c,Array.prototype.slice.call(arguments,1),b,!0)}),a._data(this,c,a.guid++)),!1},teardown:function(){return this!==document&&a.event.remove(document,c+"."+a._data(this,c)),!1}}}),a.event.special.ready={setup:function(){this===document&&d("'ready' event is deprecated")}};var M=a.fn.andSelf||a.fn.addBack,N=a.fn.find;if(a.fn.andSelf=function(){return d("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()"),M.apply(this,arguments)},a.fn.find=function(a){var b=N.apply(this,arguments);return b.context=this.context,b.selector=this.selector?this.selector+" "+a:a,b},a.Callbacks){var O=a.Deferred,P=[["resolve","done",a.Callbacks("once memory"),a.Callbacks("once memory"),"resolved"],["reject","fail",a.Callbacks("once memory"),a.Callbacks("once memory"),"rejected"],["notify","progress",a.Callbacks("memory"),a.Callbacks("memory")]];a.Deferred=function(b){var c=O(),e=c.promise();return c.pipe=e.pipe=function(){var b=arguments;return d("deferred.pipe() is deprecated"),a.Deferred(function(d){a.each(P,function(f,g){var h=a.isFunction(b[f])&&b[f];c[g[1]](function(){var b=h&&h.apply(this,arguments);b&&a.isFunction(b.promise)?b.promise().done(d.resolve).fail(d.reject).progress(d.notify):d[g[0]+"With"](this===e?d.promise():this,h?[b]:arguments)})}),b=null}).promise()},c.isResolved=function(){return d("deferred.isResolved is deprecated"),"resolved"===c.state()},c.isRejected=function(){return d("deferred.isRejected is deprecated"),"rejected"===c.state()},b&&b.call(c,c),c}}}(jQuery,window);
804\ No newline at end of file
805
806=== modified file 'openlp/plugins/remotes/html/openlp.js'
807--- openlp/plugins/remotes/html/openlp.js 2016-01-05 19:32:12 +0000
808+++ openlp/plugins/remotes/html/openlp.js 2016-12-15 18:14:46 +0000
809@@ -345,40 +345,42 @@
810 $.mobile.defaultPageTransition = "none";
811 });
812 // Service Manager
813-$("#service-manager").live("pagebeforeshow", OpenLP.loadService);
814-$("#service-refresh").live("click", OpenLP.loadService);
815-$("#service-next").live("click", OpenLP.nextItem);
816-$("#service-previous").live("click", OpenLP.previousItem);
817-$("#service-blank").live("click", OpenLP.blankDisplay);
818-$("#service-theme").live("click", OpenLP.themeDisplay);
819-$("#service-desktop").live("click", OpenLP.desktopDisplay);
820-$("#service-show").live("click", OpenLP.showDisplay);
821+$("#service-manager").on("pagebeforeshow", OpenLP.loadService);
822+$("#service-refresh").on("click", OpenLP.loadService);
823+$("#service-next").on("click", OpenLP.nextItem);
824+$("#service-previous").on("click", OpenLP.previousItem);
825+$("#service-blank").on("click", OpenLP.blankDisplay);
826+$("#service-theme").on("click", OpenLP.themeDisplay);
827+$("#service-desktop").on("click", OpenLP.desktopDisplay);
828+$("#service-show").on("click", OpenLP.showDisplay);
829 // Slide Controller
830-$("#slide-controller").live("pagebeforeshow", OpenLP.loadController);
831-$("#controller-refresh").live("click", OpenLP.loadController);
832-$("#controller-next").live("click", OpenLP.nextSlide);
833-$("#controller-previous").live("click", OpenLP.previousSlide);
834-$("#controller-blank").live("click", OpenLP.blankDisplay);
835-$("#controller-theme").live("click", OpenLP.themeDisplay);
836-$("#controller-desktop").live("click", OpenLP.desktopDisplay);
837-$("#controller-show").live("click", OpenLP.showDisplay);
838+$("#slide-controller").on("pagebeforeshow", OpenLP.loadController);
839+$("#controller-refresh").on("click", OpenLP.loadController);
840+$("#controller-next").on("click", OpenLP.nextSlide);
841+$("#controller-previous").on("click", OpenLP.previousSlide);
842+$("#controller-blank").on("click", OpenLP.blankDisplay);
843+$("#controller-theme").on("click", OpenLP.themeDisplay);
844+$("#controller-desktop").on("click", OpenLP.desktopDisplay);
845+$("#controller-show").on("click", OpenLP.showDisplay);
846 // Alerts
847-$("#alert-submit").live("click", OpenLP.showAlert);
848+$("#alert-submit").on("click", OpenLP.showAlert);
849 // Search
850-$("#search-submit").live("click", OpenLP.search);
851-$("#search-text").live("keypress", function(event) {
852+$("#search-submit").on("click", OpenLP.search);
853+$("#search-text").on("keypress", function(event) {
854 if (event.which == 13)
855 {
856 OpenLP.search(event);
857 }
858 });
859-$("#go-live").live("click", OpenLP.goLive);
860-$("#add-to-service").live("click", OpenLP.addToService);
861-$("#add-and-go-to-service").live("click", OpenLP.addAndGoToService);
862+$("#go-live").on("click", OpenLP.goLive);
863+$("#add-to-service").on("click", OpenLP.addToService);
864+$("#add-and-go-to-service").on("click", OpenLP.addAndGoToService);
865 // Poll the server twice a second to get any updates.
866 $.ajaxSetup({cache: false});
867-$("#search").live("pageinit", function (event) {
868+console.log("hook");
869+$("#search").on("pageinit", function (event) {
870+ console.log("Page init!");
871 OpenLP.getSearchablePlugins();
872 });
873-setInterval("OpenLP.pollServer();", 500);
874+setInterval(OpenLP.pollServer, 500);
875 OpenLP.pollServer();
876
877=== modified file 'tests/interfaces/openlp_core_ui/test_shortcutlistform.py'
878--- tests/interfaces/openlp_core_ui/test_shortcutlistform.py 2016-02-12 19:46:04 +0000
879+++ tests/interfaces/openlp_core_ui/test_shortcutlistform.py 2016-12-15 18:14:46 +0000
880@@ -28,6 +28,7 @@
881
882 from openlp.core.common import Registry
883 from openlp.core.ui.shortcutlistform import ShortcutListForm
884+from openlp.core.ui.shortcutlistdialog import CaptureShortcutButton, ShortcutTreeWidget
885
886 from tests.interfaces import MagicMock, patch
887 from tests.helpers.testmixin import TestMixin
888@@ -227,3 +228,34 @@
889 mocked_action_shortcuts.assert_called_with(mocked_action)
890 mocked_refresh_shortcut_list.assert_called_with()
891 mocked_set_text.assert_called_with('Esc')
892+
893+
894+def test_key_press_event():
895+ """
896+ Test the keyPressEvent method
897+ """
898+ # GIVEN: A checked button and a mocked event
899+ button = CaptureShortcutButton()
900+ button.setChecked(True)
901+ mocked_event = MagicMock()
902+ mocked_event.key.return_value = QtCore.Qt.Key_Space
903+
904+ # WHEN: keyPressEvent is called with an event that should be ignored
905+ button.keyPressEvent(mocked_event)
906+
907+ # THEN: The ignore() method on the event should have been called
908+ mocked_event.ignore.assert_called_once_with()
909+
910+
911+def test_keyboard_search():
912+ """
913+ Test the keyboardSearch method of the ShortcutTreeWidget
914+ """
915+ # GIVEN: A ShortcutTreeWidget
916+ widget = ShortcutTreeWidget()
917+
918+ # WHEN: keyboardSearch() is called
919+ widget.keyboardSearch('')
920+
921+ # THEN: Nothing happens
922+ assert True

Subscribers

People subscribed via source and target branches

to all changes: