I am writing a greasemonkey script to manipulates the DOM, queries a server and displays the result on a separate jquery dialog.
I want to add following two functionalities to it:
Provide a search box which acts like a simple search on a browser (i.e. searches through the content of the jquery dialog only and highlights the text).
Provide a text-box, the content of which should be stored permanently for all future use of the userscript unless the user changes it specifically.
The problem I am facing is that I want to include both of these in the ui-dialog-buttonpane area of the dialog, to the left of the close button, but I am not able to figure out how to do that.
What I do know is that I can use window.find() (as used here http://www.javascripter.net/faq/searchin.htm) to enable the browser find functionality.
Can someone help me with this ? Following is the code for my existing greasemonkey script:
// ==UserScript==
// #name Query for each URL Asynchronously
// #namespace SupportScript
// #include *
// #require https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js
// #require https://ajax.googleapis.com/ajax/libs/jquery/ui/1.11.0/jquery-ui.min.js
// #resource jqUI_CSS https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/redmond/jquery-ui.css
// #grant GM_addStyle
// #grant GM_getResourceText
// #grant GM_getResourceURL
// #run-at document-end
// allow pasting
// ==/UserScript==
var snapshotResults = document.evaluate('//a[contains(#href,"http")]/#href', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
var windowWidth = $(window).width()-800;
var windowHeight = $(window).height();
var zNode = document.createElement ('input');
zNode.setAttribute ('id', 'SSButton');
zNode.setAttribute( 'type', 'image' );
zNode.setAttribute( 'src', 'http://www.veryicon.com/icon/64/System/Longhorn%20R2/Back%20Button.png');
//zNode.setAttribute( 'src', 'https://dperkins.org/2013/2013-07-24.Icon.2.png');
//zNode.setAttribute( 'src','http://i1043.photobucket.com/albums/b433/suzuki800/Button-Info-icon.png');
document.body.appendChild (zNode);
var batchSize = 10;
var urlsToUpsert = [];
var uniqueHostnameSet = new Set();
var uniqueURLArray = [];
uniqueHostnameSet.add(window.location.hostname);
var finalUrl = window.location.protocol + '//' + window.location.hostname;
uniqueURLArray.push(finalUrl);
for (var iterate = 0; iterate < snapshotResults.snapshotLength; iterate++)
{
var hrefContent = snapshotResults.snapshotItem(iterate).textContent;
var regex = /http.*/;
var href = regex.exec(hrefContent);
var a = document.createElement('a');
a.href = href;
if (!uniqueHostnameSet.has(a.hostname))
{
uniqueHostnameSet.add(a.hostname);
finalUrl = a.protocol + '//' + a.hostname;
uniqueURLArray.push(finalUrl);
}
}
var divMain = '<div id="SSOverlayDialog"></div>';
$('body').append(divMain);
$.Coral = function (options) {
$.extend(options, {
url: "my URL",
data: JSON.stringify(options.data),
dataType: 'json',
crossDomain: true,
type: 'POST',
contentType: 'application/json',
processData: false,
headers: {
'Content-Encoding': 'abc',
'X-Target': options.operation
},
dataFilter: function(data, type) {
return data || "{}";
}
});
return $.ajax(options);
};
$.GetOperation = function (options) {
$.extend(options, {
async: true,
success: function(data) {
handleData(data);
},
operation: 'opeartion1'
});
return $.Coral(options);
};
$.UpsertOperation = function (options) {
$.extend(options, {
async: true,
operation: 'Operation2'
});
return $.Coral(options);
};
for (var iterateUniqueURLArray=0; iterateUniqueURLArray<uniqueURLArray.length; iterateUniqueURLArray+=batchSize) {
var urlList = uniqueURLArray.slice(iterateUniqueURLArray,iterateUniqueURLArray+batchSize);
try {
var listOfURLs = {
storeUrlList: urlList
};
var dataGetAttributes = {data: listOfURLs};
$.GetOperation(dataGetAttributes);
} catch(e) {
console.log(e);
}
}
function handleData (data) {
var div = '<div id="SSOverlayDialog">';
var response = JSON.stringify(data);
var subString = "";
var startIndex = response.indexOf('{',1);
var endIndex = response.lastIndexOf('}');
var responseText = response.substring(startIndex,endIndex);
var subString = JSON.parse(responseText);
$.each( subString, function( key, value ) {
key = JSON.stringify(key);
div+='<b><i><a style="color:#0645AD" href="'+key.substring(1,key.length-1)+'"><u>' + key.substring(1,key.length-1) + '</u></a></i></b><br><br>';
if(JSON.stringify(value)==='{}') {
console.log("Value for URL "+key+" is null.");
div+='<p>This URL does not exist with Mobius.<span style="color:red" class="urlNotPresent" id ="'+key.substring(1,key.length-1)+'"><u>Click Here</u></span> to submit to Mobius.</p>';
}
$.each( value, function( ky, val ) {
ky = JSON.stringify(ky);
if (val==null) {
div += '<p><b>'+ky.substring(1,ky.length-1)+': </b><i>'+val+'</i></p>';
}
else{
val = JSON.stringify(val);
div += '<p><b>'+ky.substring(1,ky.length-1)+': </b><i>'+val.substring(1,val.length-1)+'</i></p>';
};
});
div+='<br>';
});
div += '</div>';
$('#SSOverlayDialog').append(div);
$(".urlNotPresent").off('click');
$(".urlNotPresent").one('click', urlNotPresentFn);
$(".urlNotPresent").hover(pointerToClick, pointerToDefault);
}
var urlNotPresentFn = function() {
var url = jQuery(this).attr("id");
if (urlsToUpsert.length == batchSize-1) {
urlsToUpsert.push(url);
var listOfURLs = {
storeUrlList: urlsToUpsert
};
var myOptions = {data: listOfURLs};
$.UpsertOperation(myOptions);
urlsToUpsert.length = 0;
} else {
urlsToUpsert.push(url);
};
console.log(urlsToUpsert);
}
var pointerToClick = function() {
$(".urlNotPresent").css("cursor", "pointer");
}
var pointerToDefault = function(){
$(".urlNotPresent").css("cursor", "default");
}
$(window).bind('beforeunload', function() {
if(urlsToUpsert.length>0) {
var listOfURLs = {
storeUrlList: urlsToUpsert
};
var myOptions = {data: listOfURLs};
$.UpsertOperation(myOptions);
urlsToUpsert.length = 0;
};
return ;
});
$('#SSOverlayDialog').dialog({
autoOpen: false,
modal: false,
title: 'Discovered URLs (press "Esc" button to close)',
position: {
at: 'right top'
},
resizable: false,
width: windowWidth,
height: windowHeight,
open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); },
zIndex: 11111111,
buttons: [
{
text: 'Close',
click: function () {
$(this).dialog('close');
}
}
]
});
$("#SSButton").click(function() {
($("#SSOverlayDialog").dialog("isOpen") == false) ? $("#SSOverlayDialog").dialog("open") : $("#SSOverlayDialog").dialog("close") ;
/* if ($("#SSOverlayDialog").dialog("isOpen") == false) {
$("#SSOverlayDialog").dialog("open"),
$('#SSButton').css({
'transform': 'rotate(180deg)',
'transform': 'translate(-windowWidth)'
});
} else{
$("#SSOverlayDialog").dialog("close"),
$('#SSButton').css({
'transform': 'initial'
});
};*/
});
var jqUI_CssSrc = GM_getResourceText('jqUI_CSS');
jqUI_CssSrc = jqUI_CssSrc.replace(/\.ui-front \{[\s]*z-index:\s100\;[\s]*\}/g,".ui-front \{\n z-index: 20000000 \; \n\}");
GM_addStyle(jqUI_CssSrc);
GM_addStyle ( multilineStr ( function () {/*!
#SSButton {
background: none repeat scroll 0% 0% ;
background-image: none;
background-repeat: repeat;
background-attachment: scroll;
background-position: 0% 0%;
background-size: auto auto;
overflow: hidden;
position: absolute;
top: 0;
right: 0;
z-index: 22222222;
width: 40px;
height: 40px;
}
*/} ) );
function multilineStr (multiLineStringFn) {
var str = multiLineStringFn.toString ();
str = str.replace (/^[^\/]+\/\*!?/, '') // Strip function () { /*!
.replace (/\s*\*\/\s*\}\s*$/, '') // Strip */ }
.replace (/\/\/.+$/gm, '') // Double-slash comments wreck CSS. Strip them.
;
return str;
}
To include controls to the left of the "Close" button in a ui-dialog-buttonpane, you can use the .prepend() function on the .ui-dialog-buttonset class like this:
$('.ui-dialog .ui-dialog-buttonset').prepend('<input type="text"/><button class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span class="ui-button-text">Search</span></button>');
You'll most likely want to add a selector for the specific dialog you're using to avoid adding this control to any dialog on the page. Based on your example, it would be something like this:
$('div[aria-describedby=SSOverlayDialog]').find('.ui-dialog-buttonset').prepend('<input type="text"/><button class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span class="ui-button-text">Search</span></button>');
Hope that helps answer the main problem.
Best of luck!
Related
I have a calendar, and outside of this I have a box where I put the event values (client, barber, service and I choose a color). After loading the values, an element is generated that I can select and drag to the calendar. The following happens to me:
When I create an event and drag it to the calendar, it is placed with the color that I configured. If I click the save button, it loads correctly into the database. A json is saved with the event information, for example:
{"id":2,"title":"Maria Marco","barbero":"Diego","servicio":"Corte","start":"2020-03-21T10:30:00","end":"2020-03-21T11:00:00","color":"rgb(0, 86, 179)"}
Suppose I don't have any items in the database, and I create 3 events and drag them to the calendar. If I click the save button, these 3 will be saved correctly as indicated above.
Now if I do a new event load, these new elements will load correctly, but in the previous elements the color property now disappears.
I appreciate if any find the error in this spaghetti of js
$(function() {
var containerEl = document.getElementById('external-events');
var calendarEl = document.getElementById('calendar');
// initialize the external events
// -----------------------------------------------------------------
new FullCalendarInteraction.Draggable(containerEl, {
itemSelector: '.external-event',
eventData: function(eventEl) {
var barbero = $("#barbero").children(".opcion-barbero:selected").html()
var servicio = $("#servicio").val()
return {
title: eventEl.innerText,
extendedProps: { "barbero": barbero, "servicio": servicio, "color": eventEl.style.backgroundColor },
backgroundColor: eventEl.style.backgroundColor,
borderColor: eventEl.style.backgroundColor
};
}
});
view = 'timeGridDay';
header = {
left: 'prev,next timeGridDay,timeGridWeek,dayGridMonth',
center: '',
right: ''
};
var calendar = new FullCalendar.Calendar(calendarEl, {
timeZone: 'local',
plugins: ['interaction', 'dayGrid', 'timeGrid'],
eventSources: [
// your event source
{
url: 'ajax/turnos2.ajax.php'
}
],
editable: true,
droppable: true, // this allows things to be dropped onto the calendar !!!
drop: function(info) {
info.draggedEl.parentNode.removeChild(info.draggedEl);
}
});
calendar.render();
/* ADDING EVENTS */
var currColor = '#3c8dbc' //Red by default
//Color chooser button
var colorChooser = $('#color-chooser-btn')
$('#color-chooser > li > a').click(function(e) {
e.preventDefault()
//Save color
currColor = $(this).css('color')
//Add color effect to button
$('#add-new-event').css({
'background-color': currColor,
'border-color': currColor
})
})
$('#add-new-event').click(function(e) {
e.preventDefault()
//Get value and make sure it is not null
var val = $('#new-event').val()
if (val.length == 0) {
return
}
//Create events
var event = $('<div />')
event.css({
'font-weight': 300,
'background-color': currColor,
'border-color': currColor,
'color': '#fff'
}).addClass('external-event')
event.html(val)
$('#external-events').prepend(event)
//Add draggable funtionality
ini_events(event)
//Remove event from text input
$('#new-event').val('')
})
/*==============================================
Apply changes to the events
==============================================*/
$(document).on("click", "span.guardarCalendario", function() {
var arrayEventos = new Array();
var eventos = calendar.getEvents();
// Contador para ID
var num = 1;
eventos.forEach(e => {
// Nombre del turno
title = (e._def["title"]);
barbero2 = (e._def.extendedProps["barbero"]);
servicio = (e._def.extendedProps["servicio"]);
color = (e._def.extendedProps["color"]);
id = num;
num = num + 1;
var evento = new Object();
evento["id"] = id;
evento["title"] = title;
evento["barbero"] = barbero2;
evento["servicio"] = servicio;
evento["start"] = start;
evento["end"] = end;
evento["color"] = (e._def.extendedProps["color"]);
arrayEventos.push(evento);
})
$("#turnos").val(JSON.stringify(arrayEventos))
var data = { 'data': JSON.stringify(arrayEventos) }
$.ajax({
type: 'POST',
url: 'ajax/turnos.ajax.php',
dataType: 'json',
data: data,
success: function(data, status, xhr) {
alert("response was " + data);
},
error: function(xhr, status, errorMessage) {
$("#debug").append("RESPONSE: " + xhr.responseText + ", error: " + errorMessage);
}
});
})
turnos.ajax.php
<?php
require_once "../modelos/turnos.modelo.php";
require_once "../controladores/turnos.controlador.php";
class AjaxTurnos{
public $data;
public function ajaxActualizarTurnos(){
$datos = ($this->data);
foreach(json_decode($datos) as $value){
$respuesta = ModeloTurnos::mdlActualizarTurnos(json_encode($value).PHP_EOL);
}
return $respuesta;
}
}
/*==============================
ACTUALIZAR TURNOS
==============================*/
if(isset($_POST["data"])){
ModeloTurnos::mdlTruncarTurnos();
$turnos = new AjaxTurnos();
$turnos -> data = $_POST["data"];
$turnos -> ajaxActualizarTurnos();
}
turnos2.ajax.php
<?php
require_once "../modelos/turnos.modelo.php";
require_once "../controladores/turnos.controlador.php";
$data = ControladorTurnos::ctrMostrarTurnos();
$data2 = [];
foreach($data as $key=>$value){
$data2[] = json_decode($value["datos"]);
}
//returns data as JSON format
echo (json_encode($data2));
Auto-complete is not getting fired when pressing white-space in the editor, Is there an option to fire Autocomplete when white space is pressed?
Please have a look at this demo:
[jsfiddle] https://jsfiddle.net/xbaha/cbfe6tx4/53/
I want the auto complete to be fired when i type "my name is " (note there is a space after "is"), then using onchange event i added the suggestions that should pop up, but it does not work, i must type a letter character so that autocomplete is getting fired.
is there a solution for this?
Instead of using enableLiveAutocomplete option you can use a custom handler for afterExec event https://github.com/ajaxorg/ace/blob/v1.4.7/lib/ace/ext/language_tools.js#L149
var editor;
var fieldsList = [];
function initAceEditor() {
editor = ace.edit("aceEditor", {
theme: "ace/theme/solarized_light",
mode: "ace/mode/text",
showPrintMargin: false,
fontSize: "24px",
minLines: 3,
maxLines: 8,
wrap: true,
// do not use live autocomplete since we want to invoke more often
// enableLiveAutocompletion: true,
enableBasicAutocompletion: true,
});
var langTools = ace.require("ace/ext/language_tools");
var stepLineCompleter = {
getCompletions: function(editor, session, pos, prefix, callback) {
var completions = [];
console.log('before foreach....', this.fields, fieldsList);
var cursor = session.selection.cursor
var line = session.getLine(cursor.row).slice(0, cursor.column - prefix.length)
var fieldsList
if (line.endsWith("name is ")) {
fieldsList = ["bob", "james", "alex", "jimmy"];
} else {
fieldsList = ["my name is", "completion2", "completion3", "one more"]
}
fieldsList.forEach(function(w) {
completions.push({
value: w,
});
});
callback(null, completions);
}
}
langTools.setCompleters([stepLineCompleter]);
langTools.addCompleter(stepLineCompleter);
var Autocomplete = ace.require("ace/autocomplete").Autocomplete
var doLiveAutocomplete = function(e) {
var editor = e.editor;
var hasCompleter = editor.completer && editor.completer.activated;
var session = editor.session
var cursor = session.selection.cursor
var line = session.getLine(cursor.row).slice(0, cursor.column)
// We don't want to autocomplete with no prefix
if (e.command.name === "backspace") {
// do not hide after backspace
} else if (e.command.name === "insertstring") {
if (!hasCompleter) {
// always start completer
var completer = Autocomplete.for(editor);
// Disable autoInsert
completer.autoInsert = false;
completer.showPopup(editor);
}
}
};
editor.commands.on('afterExec', doLiveAutocomplete);
}
initAceEditor()
#aceEditor {
position: absolute;
top: 10%;
right: 0;
bottom: 30%;
left: 0;
}
<script src="https://rawgithub.com/ajaxorg/ace-builds/master/src/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="https://rawgithub.com/ajaxorg/ace-builds/master/src/ext-language_tools.js" type="text/javascript" charset="utf-8"></script>
<div id="aceEditor"></div>
I am trying to modify this example http://waynegm.github.io/imgNotes/examples/basic_interactive.html#
in order to get a select option to appear inside the dialog box when user clicks on the image. Currently the code places a marker on the area the user selects when in edit mode and opens a dialog box allowing them to enter text, with the options to save / cancel.
Inside the dialog box I want to change the textarea to a select list like:
<select>
<option value="head">Head</option>
<option value="leftarm">Left Arm</option>
<option value="rightarm">Right Arm</option>
<option value="leg">Leg</option>
</select>
It seems like it should be a simple change, I have made others samples where simple on image click makes the drop down appear. But this example has everything else I need like the options to delete and recording the co-ords of the place marker.
The current HTML:
<html>
<head>
<title>jQuery imgNotes - Interactive Base</title>
<style type="text/css" media="all">#import "css/marker.css";</style>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css" media="screen">
<script type="text/javascript" src="src/imgNotes.js"></script>
</head>
<body>
<div id="imgdiv" style="text-align: center">
<img id="image" src="image/personsit.jpg" style="border: 30px solid #ccc; padding:20px;" width=400/>
<br/>
<button id="toggleEdit">Edit</button> <button id="export">Export</button>
</div>
<div id=txt></div>
<script type="text/javascript">
;(function($) {
$(document).ready(function() {
var $img = $("#image").imgNotes();
//$img.imgNotes("import", [ {x: "0.5", y:"0.5", note:"AFL Grand Final Trophy"},
// {x: "0.4", y:"0.269", note: "Shoulder"},
// {x: "0.824", y: "0.593", note: "Fluffy microphone"}]);
var $toggle = $("#toggleEdit");
if ($img.imgNotes("option","canEdit")) {
$toggle.text("View");
} else {
$toggle.text("Edit");
}
$toggle.on("click", function() {
var $this = $(this);
if ($this.text()=="Edit") {
$this.text("View");
$img.imgNotes("option", "canEdit", true);
} else {
$this.text('Edit');
$img.imgNotes('option', 'canEdit', false);
}
});
var $export = $("#export");
$export.on("click", function() {
var $table = $("<table/>").addClass("gridtable");
var notes = $img.imgNotes('export');
$table.append("<th>X</th><th>Y</th><th>NOTE</th>");
$.each(notes, function(index, item) {
$table.append("<tr><td>" + item.x + "</td><td>" + item.y + "</td><td>" + item.note + "</td></tr>");
});
$('#txt').html($table);
});
});
})(jQuery);
</script>
</body>
</html>
imgNotes.js file
;(function($) {
$.widget("wgm.imgNotes", {
options: {
zoom: 1,
zoomStep: 0.1,
zoomable: true,
canEdit: false,
vAll: "middle",
hAll: "middle",
/*
* Default callback to create a marker indicating a note location
* See the examples for more elaborate alternatives.
*/
onAdd: function() {
this.options.vAll = "bottom";
this.options.hAll = "middle";
return $(document.createElement('span')).addClass("marker black").html(this.noteCount);
},
/*
* Default callback when the marker is clicked and the widget has canEdit = true
* Opens a dialog with a textarea to write a note.
* See the examples for a more elaborate alternative that includes a WYSIWYG editor
*/
onEdit: function(ev, elem) {
var $elem = $(elem);
$("#dialog-2").remove();
return $('<div id="dialog-2"></div>').dialog({
title: "Body Parts",
resizable: false,
modal: true,
height: "300",
width: "450",
position: { my: "left bottom", at: "right top", of: elem},
buttons: {
"Save": function() {
var txt = $('textarea', this).val();
// Put the editied note back into the data area of the element
// Very important that this step is included in custom callback implementations
$elem.data("note", txt);
$(this).dialog("close");
},
"Delete": function() {
$elem.trigger("remove");
$(this).dialog("close");
},
Cancel: function() {
$(this).dialog("close");
}
},
open: function() {
$(this).css("overflow", "hidden");
var textarea = $('<textarea id="txt" style="height:100%; width:100%;">');
$(this).html(textarea);
// Get the note text and put it into the textarea for editing
textarea.val($elem.data("note"));
}
})
},
/*
* Default callback when the marker is clicked and the widget has canEdit = false
* Opens a dialog displaying the contents of the marker's note
* See examples for alternatives such as using tooltips.
*/
onShow: function(ev, elem) {
var $elem = $(elem);
$('#NoteDialog').remove();
return $('<div id="NoteDialog"></div>').dialog({
modal: false,
resizable: false,
height: 300,
width: 250,
position: { my: "left bottom", at: "right top", of: elem},
buttons: {
"Close" : function() {
$(this).dialog("close");
}
},
open: function() {
// Get the note text and put it into the textarea for editing
$(this).html($elem.data("note"));
$(this).closest(".ui-dialog").find(".ui-dialog-titlebar:first").hide();
},
close: function() {
$(this).dialog("destroy");
}
});
},
/*
* Default callback when the markers are repainted
*/
onUpdateMarker: function(elem) {
var $elem = $(elem);
var $img = $(this.img);
var pos = $img.imgViewer("imgToView", $elem.data("relx"), $elem.data("rely"));
if (pos) {
$elem.css({
left: (pos.x - $elem.data("xOffset")),
top: (pos.y - $elem.data("yOffset")),
position: "absolute"
});
}
},
/*
* Default callback when the image view is repainted
*/
onUpdate: function() {
var self = this;
$.each(this.notes, function() {
self.options.onUpdateMarker.call(self, this);
});
}
},
_create: function() {
var self = this;
if (!this.element.is("img")) {
$.error('imgNotes plugin can only be applied to img elements');
}
// the note/marker elements
self.notes = [];
// the number of notes
self.noteCount = 0;
// the original img element
self.img = self.element[0];
var $img = $(self.img);
// attach the imgViewer plugin for zooming and panning with a custon click and update callbacks
$img.imgViewer({
onClick: function(ev, imgv) {
if (self.options.canEdit) {
ev.preventDefault();
var rpos = imgv.cursorToImg(ev.pageX, ev.pageY);
if (rpos) {
var elem = self.addNote(rpos.x, rpos.y);
self._trigger("onEdit", ev, elem);
}
}
},
onUpdate: function(ev, imgv) {
self.options.zoom = imgv.options.zoom;
self.options.onUpdate.call(self);
},
zoom: self.options.zoom,
zoomStep: self.options.zoomStep,
zoomable: self.options.zoomable
});
$img.imgViewer("update");
},
/*
* Remove the plugin
*/
destroy: function() {
this.clear();
$(this.img).imgViewer("destroy");
$.Widget.prototype.destroy.call(this);
},
_setOption: function(key, value) {
switch(key) {
case 'vAll':
switch(value) {
case 'top': break;
case 'bottom': break;
default: value = 'middle';
}
break;
case 'hAll':
switch(value) {
case 'left': break;
case 'right': break;
default: value = 'middle';
}
break;
}
var version = $.ui.version.split('.');
if (version[0] > 1 || version[1] > 8) {
this._super(key, value);
} else {
$.Widget.prototype._setOption.apply(this, arguments);
}
switch(key) {
case 'zoom':
$(this.img).imgViewer("option", "zoom", value);
break;
case 'zoomStep':
$(this.img).imgViewer("option", "zoomStep", value);
break;
case 'zoomable':
$(this.img).imgViewer("option", "zoomable", value);
break;
}
},
/*
* Pan the view to be centred at the given relative image location
*/
panTo: function(relx, rely) {
return $(this.img).imgViewer("panTo", relx, rely);
},
/*
* Add a note
*/
addNote: function(relx, rely, text) {
var self = this;
this.noteCount++;
var elem = this.options.onAdd.call(this);
var $elem = $(elem);
$(this.img).imgViewer("addElem",elem);
$elem.data("relx", relx).data("rely", rely).data("note", text);
switch (this.options.vAll) {
case "top": $elem.data("yOffset", 0); break;
case "bottom": $elem.data("yOffset", $elem.height()); break;
default: $elem.data("yOffset", Math.round($elem.height()/2));
}
switch (this.options.hAll) {
case "left": $elem.data("xOffset", 0); break;
case "right": $elem.data("xOffset", $elem.width()); break;
default: $elem.data("xOffset", Math.round($elem.width()/2));
}
$elem.click(function(ev) {
ev.preventDefault();
if (self.options.canEdit) {
self._trigger("onEdit", ev, elem);
} else {
self._trigger("onShow", ev, elem);
}
});
$elem.on("remove", function() {
self._delete(elem);
});
this.notes.push(elem);
$(this.img).imgViewer("update");
return elem;
},
/*
* Number of notes
*/
count: function() {
return this.noteCount;
},
/*
* Delete a note
*/
_delete: function(elem) {
this.notes = this.notes.filter(function(v) { return v!== elem; });
$(elem).off();
$(elem).remove();
$(this.img).imgViewer("update");
},
/*
* Clear all notes
*/
clear: function() {
var self = this;
var total = self.notes.length;
for ( var i = 0; i < total; i++ ){
var $this = self.notes[i];
$this.off();
$this.remove();
}
self.notes=[];
self.noteCount = 0;
},
/*
* Add notes from a javascript array
*/
import: function(notes) {
var self = this;
$.each(notes, function() {
self.addNote(this.x, this.y, this.note);
});
$(this.img).imgViewer("update");
},
/*
* Export notes to an array
*/
export: function() {
var notes = [];
$.each(this.notes, function() {
var $elem = $(this);
notes.push({
x: $elem.data("relx"),
y: $elem.data("rely"),
note: $elem.data("note")
});
});
return notes;
}
});
})(jQuery);
I would really appreciate if anyone could help me out.
I need to loop thru div's and load them using the promise pattern but apparently only the data from the last call gets displayed.
Here is my code
$('div[class=ceTable]').each(function () {
var position = $(this).position();
gridID = $(this).attr('id')
tableID = $(this).attr("data-tableid")
docId = $(this).attr("data-docid")
headerFound = $(this).data("headerFound")
headerArray = $(this).data("headerArray")
columnCount = $(this).data("columnCount")
$.ajax({
type: "GET",
dataType: "json",
url: "ajaxGetTableData",
data: {
'docID': docId,
'tableID': tableID
},
beforeSend: function () {
$('#' + gridID).block({
css: {
border: 'none',
padding: '15px',
backgroundColor: '#36a9e1',
'-webkit-border-radius': '10px',
'-moz-border-radius': '10px',
opacity: 5,
color: '#fff'
},
message: 'Loading Grid'
});
}
}).done(function (data) {
console.log(data, "ajaxGetTableData")
ceFeature.generateGridFromJSONObject({
tabledata: data,
columnCount: columnCount,
gridID: gridID,
headerArray: headerArray,
headerFound: headerFound
})
$('#' + gridID).unblock();
})
Your variables are implicitly global (as you forgot the var keyword) so each iteration will overwrite the previous values. The async callbacks will only access the last one then - the typical creating functions in a loop problem.
To fix this, make the variables local to the function (the each callback) so that it makes the success callback a closure with the respective variables in its scope:
$('div[class=ceTable]').each(function () {
var position = $(this).position(),
gridID = $(this).attr('id'),
tableID = $(this).attr("data-tableid"),
docId = $(this).attr("data-docid"),
headerFound = $(this).data("headerFound"),
headerArray = $(this).data("headerArray"),
columnCount = $(this).data("columnCount");
…
Using a closure:
$('div[class=ceTable]').each(function () {
var position = $(this).position();
gridID = $(this).attr('id')
tableID = $(this).attr("data-tableid")
docId = $(this).attr("data-docid")
headerFound = $(this).data("headerFound")
headerArray = $(this).data("headerArray")
columnCount = $(this).data("columnCount")
(function (columnCount, gridID, headerArray, headerFound) {
$.ajax().done();
}(columnCount, gridID, headerArray, headerFound));
});
It works perfect in all major browsers, but not in IE7.
The Java script code is:
$(function() {
var $hdVid = jQuery.noConflict();
$hdVid(function() {
$hdVid('.hd-flv-player').hdVideo();
});
});
JQuery is:
(function($) {
// plugin definition
$.fn.hdVideo = function(options) {
// build main options before element iteration
var defaults = {
theme: 'simpledark',
childtheme: ''
};
var options = $.extend(defaults, options);
// iterate and reformat each matched element
return this.each(function() {
var $hdVideo = $(this);
$hdVideo.removeAttr('controls');
//create html structure
//main wrapper
var $video_wrap=$('<div id="hd-player"></div>');
var $video_hd_html_player = $('<div id="hd_html_player"></div>').addClass('hd-video-player').addClass(options.theme).addClass(options.childtheme);
//controls wraper
var $video_controls = $('<div class="hd-video-main-control"></div><div class="hd-video-controls"><div class="hd-video-seek-container"><div class="hd-video-seek"></div></div><div class="hd-video-buffer-container"><div class="hd-video-buffer"></div></div><div class="hd-video-options cf"><a class="hd-video-play" title="Play/Pause"></a><div class="hd-video-timer"><span class="hd-video-timer-curr">00:00</span><span class="hd-video-sep"> / </span><span class="hd-video-timer-tot-time">00:00</span></div><div class="hd-full-screen"><a class="hd-full-screen-button" title="Normal/FullScreen"></a></div><div class="hd-volume-box"><div class="hd-volume-slider-container"><div class="hd-volume-slider"></div></div><a class="hd-volume-button" title="Mute/Unmute"></a><div class="hd-volume-value-slider"></div></div><div class="hd-hd-swipe"><a class="hd-hd-swipe-button" title="High Definition / Low Definition"></a></div><div class="hd-flv-html5-switch"><a title="Switch to Flash"></a></div></div></div>');
$video_wrap.append($video_hd_html_player);
$hdVideo.wrap($video_wrap);
$hdVideo.after($video_controls);
var full_screen = 0;
//get new elements
var $video_container = $hdVideo.parent('.hd-video-player');
var $video_main_control = $('.hd-video-main-control', $video_container);
$video_controls = $('.hd-video-controls', $video_container);
var $hd_play_btn = $('.hd-video-play', $video_container);
var $hd_video_seek = $('.hd-video-seek', $video_container);
var $hd_video_buffer = $('.hd-video-buffer', $video_container);
var $hd_video_timer_curr = $('.hd-video-timer-curr', $video_container);
var $hd_video_timer_tot_time = $('.hd-video-timer-tot-time', $video_container);
var $hd_volume = $('.hd-volume-slider', $video_container);
var $hd_volume_value = $('.hd-volume-value-slider', $video_container);
var $hd_volume_btn = $('.hd-volume-button', $video_container);
var $hd_hd_swipe_btn = $('.hd-hd-swipe-button', $video_container);
var $hd_full_screen_btn = $('.hd-full-screen-button', $video_container);
var $player_change_btn = $('.hd-flv-html5-switch', $video_container);
$video_controls.hide(); // keep the controls hidden
var firstTime=1;
/* Video Elements Fetching */
var videoAttr = {};
videoAttr.poster = $("video").attr("poster");
videoAttr.src = $("source").map(function() {
return $(this).attr("src");
});
videoAttr.quality = $("source").map(function() {
return $(this).attr("data-quality");
});
videoAttr.type = $("source").map(function() {
return $(this).attr("type");
});
videoAttr.codecs = $("source").map(function() {
return $(this).attr("codecs");
});
/* Video Elements Fetching Ends */
/* Poster image into screen image */
var $video_bind_pst = $('<img class="hd-vid-poster-img" src="'+videoAttr.poster+'" data-width="544" data-height="306"><div class="hd-video-main-control"></div>');
//$hdVideo.before($video_bind_pst);
//var
//width: 630px !important; height: 354px !important; top: 0px !important; left: 0px !important; max-width: 630px !important;
/* Poster image into screen image ends*/
/* Play/Pause */
var gPlay = function() {
txt = navigator.platform ;
if(txt =='iPhone'|| txt =='Linux armv7l')
{
window.location.href = videoAttr.src[0];
}
else{
if($hdVideo.attr('paused') == false) {
$hdVideo[0].pause();
$video_main_control.removeClass("hd-video-main-control-none");
}
else {
if(firstTime)
{
$hdVideo.attr('src', vidStatistics.default_vid_src);
firstTime=0;
}
$hdVideo[0].play();
$hdVideo.attr('preload', 'auto');
$video_main_control.addClass("hd-video-main-control-none");
$hdVideo.addClass("video1-visible");
}
}
return false;
};
var hd_autoply =$("video").attr("play_auto");
if(hd_autoply=="autoplay"){
$hdVideo[0].play();
$video_main_control.addClass("hd-video-main-control-none");
$hd_play_btn.addClass('hd-paused-button');
}
$video_main_control.click(gPlay);
$hd_play_btn.click(gPlay);
$hdVideo.click(gPlay);
$hdVideo.bind('play', function() {
$hd_play_btn.addClass('hd-paused-button');
return false;
});
$hdVideo.bind('pause', function() {
$hd_play_btn.removeClass('hd-paused-button');
return false;
});
$hdVideo.bind('ended', function() {
$hd_play_btn.removeClass('hd-paused-button');
$(".hd-video-main-control").removeClass('hd-video-main-control-none');
return false;
});
var gTimeFormat=function(seconds){
var m=Math.floor(seconds/60)<10?"0"+Math.floor(seconds/60):Math.floor(seconds/60);
var s=Math.floor(seconds-(m*60))<10?"0"+Math.floor(seconds-(m*60)):Math.floor(seconds-(m*60));
return m+":"+s;
};
/* Play/Pause */
/* Progressbar Slider */
var seeksliding;
var createSeek = function() {
if($hdVideo.attr('readyState'))
{
$hd_video_timer_tot_time.text(gTimeFormat($hdVideo.attr('duration')));
var video_duration = $hdVideo.attr('duration');
$hd_video_seek.slider({
value: 0,
step: 0.01,
orientation: "horizontal",
range: "min",
max: video_duration,
animate: true,
slide: function(){
seeksliding = true;
},
stop:function(e,ui){
seeksliding = false;
$hdVideo.attr("currentTime",ui.value);
}
});
$video_controls.show();
}
else {
setTimeout(createSeek, 150);
}
return false;
};
createSeek();
var seekUpdate = function() {
var currenttime = $hdVideo.attr('currentTime');
if(!seeksliding)
{
$hd_video_seek.slider('value', currenttime);
$hd_video_timer_curr.text(gTimeFormat(currenttime));
}
return false;
};
$hdVideo.bind('timeupdate', seekUpdate);
/* Progressbar Slider */
/* Buffer Slider */
var buffersliding;
var createBuffer = function() {
if($hdVideo.attr('readyState'))
{
$hd_video_timer_tot_time.text(gTimeFormat($hdVideo.attr('duration')));
var video_duration = $hdVideo.attr('duration');
$hd_video_buffer.slider({
value: 0,
step: 0.01,
orientation: "horizontal",
range: "min",
max: video_duration,
animate: true,
disabled: true,
slide: function(){
buffersliding = true;
},
stop:function(e,ui){
buffersliding = false;
$hdVideo.attr("buffered",ui.value).end(0);
}
});
$video_controls.show();
}
else {
setTimeout(createBuffer, 150);
}
return false;
};
createBuffer();
// var buffertime = $hdVideo.get(0).buffered.end(0);
var buffertime = $hdVideo[0].buffered.end(0);
var currenttime = $hdVideo.attr('currentTime');
if(!buffersliding)
{
if(currenttime>buffertime){
$hd_video_buffer.slider('value', currenttime);
}
else{
$hd_video_buffer.slider('value', buffertime);
}
}
return false;
};
$hdVideo.bind('timeupdate', bufferUpdate);
/* Buffer Slider end*/
/* Volume Control */
var video_volume = 1;
$hd_volume.slider({
value: 0.4,
orientation: "horizontal",
range: "min",
max: 1,
step: 0.05,
animate: true,
slide:function(e,ui){
$hdVideo.attr('muted',false);
video_volume = ui.value;
$hdVideo.attr('volume',ui.value);
$hd_volume_btn.removeClass('hd-volume-mute');
if(ui.value*100 == 0) {
$hd_volume_btn.css('background-position', '-244px -126px');
}
else if(ui.value*100 <= 15) {
$hd_volume_btn.css('background-position', '-244px -96px');
}
else if (ui.value*100 <= 45) {
$hd_volume_btn.css('background-position', '-244px -66px');
}
else if (ui.value*100 <= 85) {
$hd_volume_btn.css('background-position', '-244px -36px');
}
else {
$hd_volume_btn.css('background-position', '-244px -6px');
}
}
});
var muteVolume = function() {
if($hdVideo.attr('muted')==true) {
$hdVideo.attr('muted', false);
$hd_volume.slider('value', video_volume);
$hd_volume_btn.removeClass('hd-volume-mute');
}else{
$hdVideo.attr('muted', true);
$hd_volume.slider('value', '0');
$hd_volume_btn.addClass('hd-volume-mute');
}
return false;
};
/* Volume Control */
/* Full Screen */
var fullScreen = function(){
if(full_screen == 0){
full_screen = 1;
$(".hd-video-player").addClass("fullscreen-video-container");
$(".hd-video-player video.hd-flv-player").addClass("fullscreen-video");
$(".hd-video-main-control").addClass("fullscreen-hd-video-main-control");
$(".hd-video-controls").addClass("fullscreen-control-elements");
}
else
{
full_screen = 0;
$(".hd-video-player").removeClass("fullscreen-video-container");
$(".hd-video-player video.hd-flv-player").removeClass("fullscreen-video");
$(".hd-video-main-control").removeClass("fullscreen-hd-video-main-control");
$(".hd-video-controls").removeClass("fullscreen-control-elements");
}
return false;
};
$('body').keydown(function(e){
if (e.keyCode == 27 && full_screen == 1) {
fullScreen();
}
console.log(e);
return false;
});
/* Full Screen Ends*/
/* Default Video Quality */
var defaultVideoQuality = function(videoAttr){
var vidStatistics = {};
vidStatistics.support_vid_count=0;
var i, isSupp, myVid=document.createElement('video');
for(i=videoAttr.quality.length-1; i>=0; i--)
{
path = videoAttr.src[i];
var path = videoAttr.src[i],
ext = path.substr(path.lastIndexOf('.') + 1);
isSupp = myVid.canPlayType('video/'+ext+';');
if(isSupp=="maybe" || isSupp=="probably" )
{
vidStatistics.default_vid_qty = videoAttr.quality[i];
vidStatistics.default_vid_src = videoAttr.src[i];
vidStatistics.support_vid_count++;
}
}
if(vidStatistics.default_vid_qty == "hd")
$("a.hd-hd-swipe-button").addClass("hd-hd-swipe-button-hd");
else
$("a.hd-hd-swipe-button").removeClass("hd-hd-swipe-button-hd");
return(vidStatistics);
};
/* Default Video Quality Ends*/
/* HD Available Check */
var hdAvailableCheck = function(videoAttr){
var k=0, i, isSupp, sdSupport = 0;
var myVid=document.createElement('video');
for(i=0; i<videoAttr.quality.length; i++)
{
path = videoAttr.src[i];
var path = videoAttr.src[i],
ext = path.substr(path.lastIndexOf('.') + 1);
isSupp = myVid.canPlayType('video/'+ext+';');
if(isSupp=="maybe" || isSupp=="probably" )
{
if(videoAttr.quality[i]=="hd")
k=1;
else
sdSupport=1;
}
}
if (k==0)
$hd_hd_swipe_btn.css('display', 'none');
if (sdSupport==0)
$hd_hd_swipe_btn.css('pointer-events', 'none').css('cursor', 'default');
return false;
}
/* HD Available Check Ends*/
/* Video Quality Check*/
var videoQualityCheck = function(){
var i, $currVid, currQuality;
$currVid = $hdVideo[0].currentSrc;
for(i=0; i<videoAttr.quality.length; i++) //Get current video quality
if($currVid == videoAttr.src[i])
currQuality=videoAttr.quality[i];
if(currQuality == "hd")
$("a.hd-hd-swipe-button").addClass("hd-hd-swipe-button-hd");
else
$("a.hd-hd-swipe-button").removeClass("hd-hd-swipe-button-hd");
return false;
}
/* Video Quality Check Ends*/
/* Quality Swipe */
var playerstage = 0;
var hdswipe = function(){
var currVid, currExt, currVidName, currQuality, i;
if($hdVideo.attr('paused')==false)
playerstage=1;
currVid = $hdVideo[0].currentSrc;
var currVidTime = $hdVideo.attr('currentTime');
currExt = currVid.substr(currVid.lastIndexOf('.') + 1);
for(i=0; i<videoAttr.quality.length; i++) //Get current video quality
if(currVid == videoAttr.src[i])
currQuality=videoAttr.quality[i];
for(i=0; i<videoAttr.quality.length; i++) //Swipe the Video
{
if((currExt==videoAttr.src[i].substr(videoAttr.src[i].lastIndexOf('.') + 1))&&(currQuality!= videoAttr.quality[i]))
{
$hdVideo.attr('src', videoAttr.src[i]);
resumeCurrTime(currVidTime);
gPlay();
createSeek();
createBuffer();
playerstage=0;
break;
}
}
alert(currQuality);
if(currQuality == "sd")
$("a.hd-hd-swipe-button").addClass("hd-hd-swipe-button-hd");
else
$("a.hd-hd-swipe-button").removeClass("hd-hd-swipe-button-hd");
return false;
}
var resumeCurrTime = function(currVidTime) {
if($hdVideo.attr('readyState'))
{
$hdVideo[0].currentTime = currVidTime;
}
else
setTimeout(function() { resumeCurrTime(currVidTime); }, 150);
return false;
}
/* Quality Swipe Ends */
/* HTML5 / FLV Swipe */
var playerChangeIntFn = function(){
if(full_screen==1)
fullScreen();
$hdVideo.attr('preload', 'none');
$hdVideo.load();
var trigger = "flash";
playerChange(trigger);
return false;
};
/* HTML5 / FLV Swipe Ends */
var vidStatistics = {};
vidStatistics = defaultVideoQuality(videoAttr);
hdAvailableCheck(videoAttr);
$hd_hd_swipe_btn.click(hdswipe); //HD On/Off
$hd_volume_btn.click(muteVolume); //Mute Volume
$hd_full_screen_btn.click(fullScreen); //Full Screen On/Off
$video_container.dblclick(fullScreen); //Full Screen On/Off
$player_change_btn.click(playerChangeIntFn); //Full Screen On/Off
});
};
// plugin defaults
$.fn.hdVideo.defaults = {
};
})(jQuery);
HTML is:
<video src="" width="830" height="354" class="hd-flv-player" poster="asserts/poster.png" controls="controls" data-name="demo video" data-uid="57fb2708" preload="none">
<source src="http://video-js.zencoder.com/oceans-clip.mp4" data-quality="hd"></source>
<source src="http://static.clipcanvas.com/sample/clipcanvas_14348_offline.mp4" data-quality="sd"></source>
<source src="http://video.webmfiles.org/big-buck-bunny_trailer.webm" data-quality="hd"></source>
<source src="asserts/300_VP8.webm" data-quality="sd"></source>
</video>
Doctype: <!DOCTYPE html>
Note: I know that IE7 wont support HTML5 Video. But I just want the control code should be binded. So that I can use Flash Fall back.
Reply to your comment
That error is because of ie7 support for "myVid.canPlayType()" in
JQuery
Then that needs to be fixed, no? Even though it looks like a third-party library, you can still fix code in them, and even submit bug fixes to the developer. Maybe they even have a later version of the library out, you could check.
if (myVid.canPlayType)
will check for the existence of the function in the object. If it doesn't exist, like you said it probably doesn't support HTML video. You should then exit the plugin with an error, or have an option in the plugin which content should be used as a fallback.
DEMO