Juan Camilo Mejia Juan Camilo Mejia - 4 months ago 6
Javascript Question

How to solve a conflict with primefaces jquery

Im developing a project with primefaces 5, one page uses a js file that needs jquery, but shows

Uncaught TypeError: undefined is not a function
, but when I change my jquery source from
<h:outputScript library="primefaces" name="jquery/jquery.js" target="head"/>
to

<h:head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js"></script>
</h:head>


works fine but I lost many primefaces features like
contexMenu


How can I solve this conflict?

This is my javascript file:

(function($, $S) {
//$ jQuery
//$S window.localStorage
//Variables Declaration
var $board = $('#notesForm\\:board'),
//Board where the Posticks are sticked
Postick, //Singleton Object containing the Functions to work with the LocalStorage
len = 0, //Length of Objects in the LocalStorage
currentNotes = '', //Storage the html construction of the posticks
o; //Actual Postick data in the localStorage

//Manage the Posticks in the Local Storage
//Each postick is saved in the localStorage as an Object
Postick = {
add : function(obj) {
obj.id = $S.length;
$S.setItem(obj.id, JSON.stringify(obj));
},

retrive : function(id) {
return JSON.parse($S.getItem(id));
},

remove : function(id) {
$S.removeItem(id);
},

removeAll : function() {
$S.clear();
}

};

//If exist any postick, Create it/them
len = $S.length;
if (len) {
for (var i = 0; i < len; i++) {
//Create all posticks saved in localStorage
var key = $S.key(i);
o = Postick.retrive(key);
currentNotes += '<div class="postick"';
currentNotes += ' style="left:' + o.left;
currentNotes += 'px; top:' + o.top;
//data-key is the attribute to know what item delete in the localStorage
currentNotes += 'px"><div class="toolbar"><span class="delete" data-key="'
+ key;
currentNotes += '">x</span></div><div contenteditable="true" class="editable">';
currentNotes += o.text;
currentNotes += '</div>';
}

//Append all the posticks to the board
$board.html(currentNotes);
}

//When the document is ready, make all posticks Draggable
$(document).ready(function() {
$(".postick").draggable({
cancel : '.editable',
"zIndex" : 3000,
"stack" : '.postick'
});
});

//Remove Postick
$('span.delete').live('click', function() {
if (confirm('Are you sure you want to delete this Note?')) {
var $this = $(this);
//data-key is the attribute to know what item delete in the localStorage
Postick.remove($this.attr('data-key'));
$this.closest('.postick').fadeOut('slow', function() {
$(this).remove();
});
}
});

//Create postick
$('#notesForm\\:btn-addNote')
.click(
function() {
$board
.append('<div class="postick" style="left:20px;top:70px"><div class="toolbar"><span class="delete" title="Close">x</span></div><div contenteditable class="editable"></div></div>');
$(".postick").draggable({
cancel : '.editable'
});
});

//Save all the posticks when the user leaves the page
window.onbeforeunload = function() {
//Clean the localStorage
Postick.removeAll();
//Then insert each postick into the LocalStorage
//Saving their position on the page, in order to position them when the page is loaded again
$('.postick').each(function() {
var $this = $(this);
Postick.add({
top : parseInt($this.position().top),
left : parseInt($this.position().left),
text : $this.children('.editable').text()
});
});
}
})(jQuery, window.localStorage);

Answer

PrimeFaces as being a jQuery based JSF component library already ships with jQuery (and UI) out the box. PrimeFaces loads them all by itself once you use PrimeFaces components on the page. There's absolutely no point of manually loading another jQuery files along it. It'll only conflict in all colors as you experienced.

If you actually want to use jQuery/UI on a page which doesn't necessarily include PrimeFaces components and thus jQuery/UI doesn't necessarily get auto-included, then you need to manually include the PrimeFaces-bundled jQuery as follows:

<h:outputScript library="primefaces" name="jquery/jquery.js" target="head" />
<h:outputScript library="primefaces" name="jquery/jquery-plugins.js" target="head" />

Note: this won't end up in duplicate inclusions. JSF/PrimeFaces is capable of detecting that you already manually declared them and won't auto-include another one.

Or, if you actually want to upgrade PrimeFaces-bundled jQuery/UI to a newer version, then place those files on exactly the following location and file names:

WebContent
 |-- resources
 |    `-- primefaces
 |         `-- jquery
 |              |-- jquery.js          <-- newer jQuery version
 |              `-- jquery-plugins.js  <-- newer jQuery UI version
 :

When a JSF resource is found in WAR instead of JAR, then those in WAR will have higher loading precedence over those in JARs.

If you're still facing Uncaught TypeError errors, then make sure that the jQuery snippet you found in the Internet is compatible with the PrimeFaces-bundled jQuery version. PrimeFaces 5.0 ships with jQuery 1.11.0 and jQuery UI 1.10.3. Your snippet seems to be targeted at jQuery 1.4 and a lot has been changed in the path to jQuery 1.11. So is for example $.live() deprecated in 1.7 and removed in 1.9. See also the documentation.