I've been thinking for hours about this problem and haven't been able to figure out how to do it in an elegant way.
I'm implementing a simple video player where I let the user trim the video (meaning, choose a start and end time). I get a dynamic array of videos from the server, looks something like this:
$scope.videos =
[{
id: "1",
start: 122,
end: 187,
length: 352,
url: "https://www.youtube.com/watch?v=-ePGMfDkTHo"
},
{
id: "2",
start: 122,
end: 187,
length: 352,
url: "https://www.youtube.com/watch?v=dVlM2LW90nU"
}... etc];
And with ng-repeat I display the videos on the client.
This is what I have in my view for each iframe that hold a video:
<iframe class="video" length="{{asset.length}}" start="{{asset.start}}" end="{{asset.end}}" original-url="{{ asset.url }}" data-value-start="asset.start"></iframe>
(where asset represent a video in the array)
I have a play bar where I let the user change the start and end time of the videos. Once the user changes the start and end time from the view I change the custom attributes accordingly in the iframe tag:
$scope.$apply(function()
{
$caller.attr('src',$scope.trustSrc(createEmbedUrl(url, $scope.newAssetData.start, $scope.newAssetData.end)));
$caller.attr('start', $scope.newAssetData.start);
});
My problem is, that once the user is done changing the times, I need to send back to the server the new start and end time. I was expecting that changing 'start' and 'end' attribute would change the same attributes in the video scope variable but it doesn't happen. I was thinking od "dirty" ways to solve this problem without Angular (such as adding another custom attribute in the view of 'vidId' and have it be my guide to track the new start and end times but it just seems wrong to do it.
What am I missing?
Thank you,
Mila
Related
I'm creating a website using the Crowd HTML Elements that let users/workers annotate images with the bounding box format. The form looks like this:
<crowd-form>
<crowd-bounding-box
name="annotatedResult"
labels="['Referee', 'Player']"
src="https://s3.amazonaws.com/cv-demo-images/basketball-outdoor.jpg"
header="Draw boxes around each basketball player and referee in this image"
>
<full-instructions header="Bounding Box Instructions" >
<p>Use the bounding box tool to draw boxes around the requested target of interest:</p>
<ol>
<li>Draw a rectangle using your mouse over each instance of the target.</li>
<li>Make sure the box does not cut into the target, leave a 2 - 3 pixel margin</li>
<li>
When targets are overlapping, draw a box around each object,
include all contiguous parts of the target in the box.
Do not include parts that are completely overlapped by another object.
</li>
<li>
Do not include parts of the target that cannot be seen,
even though you think you can interpolate the whole shape of the target.
</li>
<li>Avoid shadows, they're not considered as a part of the target.</li>
<li>If the target goes off the screen, label up to the edge of the image.</li>
</ol>
</full-instructions>
<short-instructions>
Draw boxes around each basketball player and referee in this image.
</short-instructions>
</crowd-bounding-box>
</crowd-form>
The results of a worker's submission looks like the following:
{
"annotatedResult": {
"boundingBoxes": [
{
"height": 3300,
"label": "Dog",
"left": 536,
"top": 154,
"width": 4361
}
],
"inputImageProperties": {
"height": 3456,
"width": 5184
}
}
}
]
I'd like to take this output and write it to a database, pass it to AWS Lambda, store it as metadata, etc. but I don't know how to access the results. Is the JSON output a property of some HTML DOM property I can grab?
I can attach a javascript function to the submit action of the crowd-form portion...
<script>
document.querySelector('crowd-form').onsubmit = function() {
???
};
</script>
...but I'm not sure what object I need to grab to get the results. Thanks for your help!
You can access the bounding boxes during the onsubmit event like this:
<script>
document.querySelector('crowd-form').onsubmit = function(e) {
const boundingBoxes = document.querySelector('crowd-bounding-box').value.boundingBoxes || document.querySelector('crowd-bounding-box')._submittableValue.boundingBoxes;
}
</script>
Here's a working jsfiddle.
Your use case sounds interesting. If you don't mind sharing, please email me at samhenry#amazon.com and I may be able to help further.
Thank you,
Amazon Mechanical Turk
How can I get the start and end time of visible days in fullcalendar?
I need it for use in another javascript instance. Is there some function like -
uiCalendarConfig.calendars['myCalendar1'].fullCalendar('getView').visStart
?
According to full-calendar documentation (jQuery plugin on on which the uiCalendar is based on) when you call fullCalendar('getView') you get back the View object with properties:
start
A Moment that is the first visible day.
end
A Moment that is the exclusive last visible day.
So you should be able to get start and end moments as follows:
uiCalendarConfig.calendars['myCalendar1'].fullCalendar('getView').start
and
uiCalendarConfig.calendars['myCalendar1'].fullCalendar('getView').end
Following example shows fullcalendar in angular 2. Should be easily adaptable to your environment. You can use the "viewRender" callback of fullcalendar to maintain the current visible date range. Useful if you intend to fetch business objects only relevant for the visible date range, etc.
var calendarDiv: any;
var self = this;
calendarDiv = $(this.elementRef.nativeElement).find('#calendar');
calendarDiv.fullCalendar({
defaultView: "agendaWeek",
...
viewRender: function (view: any, element: any) {
self.crtCalendarStart = view.start;
self.crtCalendarEnd = view.end;
self.myFilterService.setFilter("filter_plandate", {
type: 'DateTime',
value_from: view.start.toDate(),
value_to: view.end.toDate()
});
},
selectable: true,
selectHelper: false,
...
});
I've implemented the angular-advanced-searchbox (with AngularJS 1.5.8, ui-bootstrap, JQuery) like the demo-page:
html
<nit-advanced-searchbox ng-model="searchParams" parameters="availableSearchParams" placeholder="Search..."></nit-advanced-searchbox>
script
$scope.availableSearchParams = [
{...},
{
key: "city",
name: "City",
placeholder: "City...",
restrictToSuggestedValues: true,
suggestedValues: ['Berlin', 'London', 'Paris'] },
{...}
];
};
Here is a Plunker of this implementation too. I'll refer to this example to picture my problem.
If I type 'city' in the searchfield and select it by hitting enter, then I'll see the suggested Value-List (Berlin, London, Paris) for about a second and then the focus 'll lost and the selected key-value (city) is automatically removed. It seems this won't happen, if the mouse pointer is rested over the search-input field (without any action).
With this issue, I can't use this module on my site - but I really want to :) Are any suggestions out there?
OK, this (low-level) fix worked for me - i've just commented line 107 ():
angular-advanced-searchbox-tpls.js [#107]
$scope.searchQueryChanged = function (query) {
// updateModel('change', 'query', 0, query);
};
This line is used to build 'pre-queries'. If you start typing 'city', the scope of searchParams generate a temporary query on the fly and would be changed to the selected key - g.E.:
{"query":"ci"}
This will then lead to a timeout after 'city' is selected. I don't know this 'query' is used for - all things 'll do their job furthermore. But by time I'll looking to a real fix for this problem :)
Programmatically
So I am facing an issue with the select in Angular JS. This is a follow-up question to my previous question
Now I am able to load my values in the second select but I am unable to write the same value to it when the query from DB comes back. So If I select Ford in one select and Figo in another. and press save. The values go into DB correctly but when I come again to that view. Shouldn't that value persist right? I mean I should be able to see figo in the second select. But I am unable to. I tried setting to the ng-model but that method doesn't work. I have also attached a fiddle with the proper comments as to what is not working.
The code uses one of the marked answers from the question.
HTML
<select ng-model="carBrand" name="carBrand" required ng-options=" brand for brand in brands" ng-change="selectedCar(carBrand)"></select>
<select ng-model="carModel" name="carModel" required ng-options="model.name for model in cars[carIndex]"></select>
JS
$scope.brands = ['Ford', 'Honda', 'Hyundai', 'Mahindra',
'Maruti Suzuki', 'Nissan', 'Renault', 'Skoda', 'Tata', 'Toyota', 'Volksvagen'
];
$scope.cars[0] = $scope.cars[0] = [{
name: "Figo",
capacity: 45
}, {
name: "Ecosport",
capacity: 52
}, {
name: "Fiesta",
capacity: 45
}, {
name: "Endeavour",
capacity: 71
}];
$scope.carBrand = $scope.brands[0];
$scope.cars = [];
$scope.selectedCar = function(brand) {
$scope.carIndex = $scope.brands.indexOf(brand);
};
$scope.carModel = "Anything";
EDIT
I think there is an issue in the understanding of the question. All I want is programmatically(by code) set the value of the second select. That's it.
I have forked your fiddle. Have a look: https://jsfiddle.net/4ynkrj0o/2/
var MockSaveMyData = function(itemsToSave){
// I JUST SAVED ALL MY DATE !! :D
var savedItems = itemsToSave;
savedItems.CreatedAt = new Date();
savedItems.CreatedBy = 'YOU !!';
return {
then: function(callback){
callback(savedItems);
}
};
};
You will have to save and retrieve the values on every page refresh.
Like you said, you have cookies where you save your Car object. In that case, you will have to assign the object on the top firth thing inside the controller.
You will also have to update the cookies after you have run the save function. I will suggest doing all this in the success call back which http calls provide. You can update the cookie and then refresh the page. Or you can just assign the updated values and give a message to the user stating that the save call has been successful.
Again, in my opinion, you should avoid reloading the page. It almost defies the essence of Angular. Where you can do almost everything asynchronously.
I'm creating a music player for Ubuntu Touch in QML and I have some things I would appreciate some help with since I'm new to QML.
I have a list of tracks from a directory, but I want to show the meta data (artist, track name, year, album and so on) instead of the filename.
Using Qt.Multimedia am able to get the meta data from the currently playing track, but I can't find how to do it per file from my FolderListModel delegated files.
How would I do that?
This is the current code:
Column {
anchors.centerIn: parent
anchors.fill: parent
ListView {
id: musicFolder
FolderListModel {
id: folderModel
folder: musicDir
showDirs: false
nameFilters: ["*.ogg","*.mp3","*.oga","*.wav"]
}
width: parent.width
height: parent.height
model: folderModel
delegate: ListItem.Subtitled {
text: fileName
subText: "Artist: "
onClicked: {
console.debug('Debug: User pressed '+musicDir+fileName)
playMusic.source = musicDir+fileName
playMusic.play()
trackInfo.text = playMusic.metaData.albumArtist+" - "+playMusic.metaData.title // show track meta data
}
}
}
}
It seems like the easiest thing to do here would be to go get a C++ library that can parse the meta data out of these files and use it to create a custom ListModel in C++ that populates this information onto itself. Unfortunately, this will have to be done in C++ as javascript does not have the IO capabilities to read and parse files.
Actually I think I might go ahead and use QtMultimedia, but keep data in a local database. On startup, it checks the music dir and adds/removes tracks. That way it will be only be slow at first startup (hopefully)