die Downloadliste für die Filmlisten nur jeden 10. Programmstart aktualisieren
177723
public String suchenAkt(ArrayList<String> bereitsVersucht) {
        // passende URL zum Laden der Filmliste suchen
        String retUrl;
        if (listeFilmlistenUrls_akt.isEmpty()) {
            // bei leerer Liste immer aktualisieren
            updateURLsFilmlisten(true);
        } else if (firstSearchAkt) {
            // nach dem Programmstart wird die Liste einmal aktualisiert aber
            // da sich die Listen nicht ändern, nur jeden xx Start
            int nr = new Random().nextInt(UPDATE_LISTE_MAX);
            if (nr == 0) {
                updateURLsFilmlisten(true);
            }
        }
        firstSearchAkt = false;
        retUrl = (listeFilmlistenUrls_akt.getRand(bereitsVersucht)); //eine Zufällige Adresse wählen
        if (bereitsVersucht != null) {
            bereitsVersucht.add(retUrl);
        }
        return retUrl;
    }
129777
public function filesAction()
    {
        //formularz
        $form = new Form\ConnectorImportFilesForm;
        //formularz zapisany
        if ($form->isSaved()) {
            //przekazanie listy plików do downloadu
            $this->view->files = $form->getOption('data');
            //otwarcie sesji
            $session = new \Mmi\Session\SessionSpace(\Cms\Model\ConnectorModel::SESSION_SPACE);
            $this->view->downloadUrl = base64_encode($session->url);
        } else {
            //form do widoku
            $this->view->form = $form;
        }
    }
648910
def complete_media(self, text, line, begidx, endidx):
        
        choices = {'actor': query_actors,  # function
                   'director': TabCompleteExample.static_list_directors,  # static list
                   'movie_file': (self.path_complete,)
                   }
        completer = argparse_completer.AutoCompleter(TabCompleteExample.media_parser,
                                                     self,
                                                     arg_choices=choices)

        tokens, _ = self.tokens_for_completion(line, begidx, endidx)
        results = completer.complete_command(tokens, text, line, begidx, endidx)

        return results
590143
def action
      updated_list_filename = File.join(Configuration::application_root, 'upgrade_package_add_files.txt')
      removed_list_filename = File.join(Configuration::application_root, 'upgrade_package_remove_files.txt')
      mkdir_p Configuration::development_directory
      Configuration::enabled_subscriber_platforms.each { |each|
        RhoDevelopment.setup(Configuration::development_directory, each)
        puts "Check changes for #{each}".warning
        changed = RhoDevelopment.check_changes_from_last_build(updated_list_filename, removed_list_filename)
        if changed
          puts "Source code for platform #{each} was changed".primary
          WebServer.dispatch_task(PlatformPartialUpdateBuildingTask.new(each, @filename));
          Configuration::enabled_subscribers_by_platform(each).each { |subscriber|
            WebServer.dispatch_task(SubscriberPartialUpdateNotifyingTask.new(subscriber, @filename));
          }
        else
          puts "Source code for platform #{each} wasn't changed".primary
        end
      }
    end
181948
function shareReplay(bufferSize, windowTime, scheduler) {
    return function (source) { return source.lift(shareReplayOperator(bufferSize, windowTime, scheduler)); };
}
1074640
@SuppressWarnings("deprecation")
    private void buildFilmList() throws Exception {
        final NodeList subtitleData = doc.getElementsByTagName("tt:p");

        for (int i = 0; i < subtitleData.getLength(); i++) {
            final Subtitle subtitle = new Subtitle();

            final Node subnode = subtitleData.item(i);
            if (subnode.hasAttributes()) {
                // retrieve the begin and end attributes...
                final NamedNodeMap attrMap = subnode.getAttributes();
                final Node beginNode = attrMap.getNamedItem("begin");
                final Node endNode = attrMap.getNamedItem("end");
                if (beginNode != null && endNode != null) {
                    subtitle.begin = ttmlFormat.parse(beginNode.getNodeValue());
                    //HACK:: Don´t know why this is set like this...
                    //but we have to subract 10 hours from the XML
                    if (subtitle.begin.getHours() >= 10) {
                        subtitle.begin.setHours(subtitle.begin.getHours() - 10);
                    }
                    subtitle.end = ttmlFormat.parse(endNode.getNodeValue());
                    if (subtitle.end.getHours() >= 10) {
                        subtitle.end.setHours(subtitle.end.getHours() - 10);
                    }

                }
            }

            final NodeList childNodes = subnode.getChildNodes();
            for (int j = 0; j < childNodes.getLength(); j++) {
                final Node node = childNodes.item(j);
                if (node.getNodeName().equalsIgnoreCase("tt:span")) {
                    //retrieve the text and color information...
                    final NamedNodeMap attrMap = node.getAttributes();
                    final Node styleNode = attrMap.getNamedItem("style");
                    final StyledString textContent = new StyledString();

                    textContent.setText(node.getTextContent());
                    final String col = colorMap.get(styleNode.getNodeValue());
                    if (col == null) {
                        textContent.setColor(color); // gabs beim BR
                    } else {
                        textContent.setColor(colorMap.get(styleNode.getNodeValue()));
                    }
                    subtitle.listOfStrings.add(textContent);
                }
            }
            subtitleList.add(subtitle);
        }
    }
1275439
private function hookMediaList() {
		if(!$this->mediaListIntegration) {
			return;
		}

		add_action('admin_init', function() {
			add_filter('manage_media_columns', function($cols) {
				$cols["cloud"] = 'Cloud';

				return $cols;
			});

			add_action('manage_media_custom_column', function($column_name, $id) {
				if($column_name == "cloud") {
					$meta = wp_get_attachment_metadata($id);
					if(!empty($meta) && isset($meta['s3'])) {
						echo "<a href='".$meta['s3']['url']."' target=_blank>View</a>";
					}
				}
			}, 10, 2);
		});

		add_action('wp_enqueue_media', function() {
			add_action('admin_head', function() {
				if(get_current_screen()->base == 'upload') {
					?>
                    <style>
                        th.column-s3, td.column-s3 {
                            width: 60px !important;
                            max-width: 60px !important;
                        }
                    </style>
					<?php
				}
			});
		});
	}
486092
private void processFromWeb(URL source, ListeFilme listeFilme) {
        Request.Builder builder = new Request.Builder().url(source);
        builder.addHeader("User-Agent", Config.getUserAgent());

        //our progress monitor callback
        InputStreamProgressMonitor monitor = new InputStreamProgressMonitor() {
            private int oldProgress = 0;

            @Override
            public void progress(long bytesRead, long size) {
                final int iProgress = (int) (bytesRead * 100 / size);
                if (iProgress != oldProgress) {
                    oldProgress = iProgress;
                    notifyProgress(source.toString(), iProgress);
                }
            }
        };

        try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(builder.build()).execute();
             ResponseBody body = response.body()) {
            if (response.isSuccessful()) {
                try (InputStream input = new ProgressMonitorInputStream(body.byteStream(), body.contentLength(), monitor)) {
                    try (InputStream is = selectDecompressor(source.toString(), input);
                         JsonParser jp = new JsonFactory().createParser(is)) {
                        readData(jp, listeFilme);
                    }
                }
            }
        } catch (Exception ex) {
            Log.errorLog(945123641, ex, "FilmListe: " + source);
            listeFilme.clear();
        }
    }
169732
@Override
    protected void addToList() {
        //<broadcast id="1391" site="ndrfernsehen">45 Min</broadcast>
        final String ADRESSE = "https://www.ndr.de/mediathek/sendungen_a-z/index.html";
        final String MUSTER_URL1 = "<li><a href=\"/mediathek/mediatheksuche105_broadcast-";
        listeThemen.clear();

        meldungStart();

        MSStringBuilder seite = new MSStringBuilder(Const.STRING_BUFFER_START_BUFFER);
        final GetUrl getUrlIo = new GetUrl(getWartenSeiteLaden());
        seite = getUrlIo.getUri(SENDERNAME, ADRESSE, StandardCharsets.UTF_8, 5 /* versuche */, seite, ""/* meldung */);
        int pos = 0;
        int pos1;
        int pos2;
        String url = "";
        String thema = "";
        while ((pos = seite.indexOf(MUSTER_URL1, pos)) != -1) {
            try {
                pos += MUSTER_URL1.length();
                pos1 = pos;
                if ((pos2 = seite.indexOf("\"", pos)) != -1) {
                    url = seite.substring(pos1, pos2);
                }
                pos1 = seite.indexOf(">", pos);
                pos2 = seite.indexOf("<", pos);
                if (pos1 != -1 && pos2 != -1 && pos1 < pos2) {
                    thema = seite.substring(pos1 + 1, pos2);
                }
                if (url.isEmpty()) {
                    Log.errorLog(210367600, "keine Url");
                    continue;
                }
                String url_ = "https://www.ndr.de/mediathek/mediatheksuche105_broadcast-" + url;
                String[] add = new String[]{url_, thema};
                if (CrawlerTool.loadLongMax()) {
                    if (!alleSeiteSuchen(url_, thema)) {
                        // dann halt so versuchen
                        listeThemen.addUrl(add);
                    }
                } else {
                    listeThemen.addUrl(add);
                }
            } catch (Exception ex) {
                Log.errorLog(332945670, ex);
            }
        }
        // noch "Verpasst" für die letzten Tage einfügen
        // https://www.ndr.de/mediathek/sendung_verpasst/epg1490_date-2014-05-17.html
        // https://www.ndr.de/mediathek/sendung_verpasst/epg1490_date-2014-05-17_display-onlyvideo.html
        FastDateFormat formatter1 = FastDateFormat.getInstance("yyyy-MM-dd");
        FastDateFormat formatter2 = FastDateFormat.getInstance("dd.MM.yyyy");
        final int maxTage = CrawlerTool.loadLongMax() ? 30 : 20;
        for (int i = 0; i < maxTage; ++i) {
            // https://www.ndr.de/mediathek/sendung_verpasst/epg1490_date-2015-09-05_display-all.html
            final String URL = "https://www.ndr.de/mediathek/sendung_verpasst/epg1490_date-";
            final String tag = formatter1.format(new Date().getTime() - (1000 * 60 * 60 * 24 * i));
            final String date = formatter2.format(new Date().getTime() - (1000 * 60 * 60 * 24 * i));
            //String urlString = URL + tag + "_display-onlyvideo.html"; --> stimmt leider nicht immer
            final String urlString = URL + tag + "_display-all.html";
            listeThemen.addUrl(new String[]{urlString, date});
        }

        if (Config.getStop()) {
            meldungThreadUndFertig();
        } else if (listeThemen.isEmpty()) {
            meldungThreadUndFertig();
        } else {
            meldungAddMax(listeThemen.size());
            for (int t = 0; t < getMaxThreadLaufen(); ++t) {
                Thread th = new ThemaLaden();
                th.setName(SENDERNAME + t);
                th.start();
            }
        }
    }
25123
def download(client, target_dir):
    """"""
    print('')
    print('download store listings')
    print('---------------------')
    listings = client.list('listings')
    for listing in listings:
        path = os.path.join(target_dir, 'listings', listing['language'])
        mkdir_p(path)
        with open(os.path.join(path, 'listing.json'), 'w') as outfile:
            print("save listing for {0}".format(listing['language']))
            json.dump(
                listing, outfile, sort_keys=True,
                indent=4, separators=(',', ': '))
420874
public void filmeBeimSenderSuchen(boolean filmlisteUpdate) {
        // Filme bei allen Sender suchen
        if (!istAmLaufen) {
            // nicht doppelt starten
            istAmLaufen = true;
            CrawlerConfig.updateFilmliste = filmlisteUpdate;
            msFilmeSuchen.filmeBeimSenderLaden(Data.listeFilme);
        }
    }
972716
function(url, dest, callback, count) {
    if (isNaN(count)) {
      count = 10;
    }

    if (this.cache[url]) {
      return fs.writeFile(dest, this.cache[url], callback);
    }

    fs.exists(dest, function(exists) {
      if (exists) {
        // No need to download :).
        return callback && callback();
      }

      var stream = fs.createWriteStream(dest);
      debug('GET ' + url);
      var protocol = this._getProtocol(url);
      protocol.get(url, function(res) {
        if (res.statusCode !== 200) {
          debug('Bad status ' + res.statusCode + ' for ' + url + '... ' +
                'will try ' + count + ' more times');
          if (count === 0) {
            return callback && callback(
              new Error('Bad status ' + res.statusCode + ' for ' + url));
          }

          return Download.inst.downloadToDisk(url, dest, callback, count - 1);
        }

        res.pipe(stream);
        stream.on('finish', callback);
      });
    }.bind(this));
  }
260100
private void buildFilmListFlash() throws Exception {
        final NodeList subtitleData = doc.getElementsByTagName("p");

        for (int i = 0; i < subtitleData.getLength(); i++) {
            final Subtitle subtitle = new Subtitle();

            final Node subnode = subtitleData.item(i);
            if (subnode.hasAttributes()) {
                // retrieve the begin and end attributes...
                final NamedNodeMap attrMap = subnode.getAttributes();
                final Node beginNode = attrMap.getNamedItem("begin");
                final Node endNode = attrMap.getNamedItem("end");
                if (beginNode != null && endNode != null) {
                    subtitle.begin = parseFlash(beginNode.getNodeValue());
                    subtitle.end = parseFlash(endNode.getNodeValue());
                    final StyledString textContent = new StyledString();
                    textContent.setColor(color); // sicher ist sicher
                    textContent.setText(subnode.getTextContent());

                    final Node col = attrMap.getNamedItem("tts:color");
                    if (col != null) {
                        textContent.setColor(col.getNodeValue());
                    } else {
                        final NodeList childNodes = subnode.getChildNodes();
                        for (int j = 0; j < childNodes.getLength(); j++) {
                            final Node node = childNodes.item(j);
                            if (node.getNodeName().equalsIgnoreCase("span")) {
                                //retrieve the text and color information...
                                final NamedNodeMap attr = node.getAttributes();
                                final Node co = attr.getNamedItem("tts:color");
                                textContent.setColor(co.getNodeValue());
                            }
                        }
                    }
                    subtitle.listOfStrings.add(textContent);

                }
            }
            subtitleList.add(subtitle);
        }
    }
1044383
def preprocess(self, data):
        

        print 'Beginning pre-process...'
        for url, video in data['media'][0]['clipData'].iteritems():
            print 'Downloading {0} from {1}.'.format(video['title'], url)

            # Removes all white spaces and non alphanumeric chars from title
            video['title'] = re.sub(
                '[^\w\.]',
                '',
                video['title']
            ) + '.webm'

            urllib.urlretrieve(url, video['title'])
            self.base_videos.append(video['title'])
            print 'video downloaded as %s!' % video['title']
        print 'All videos downloaded.'

        events = [event for track in data['media'][0]['tracks']
                  for event in track['trackEvents']]

        for event in events:
            if event['type'] == 'skip' or event['type'] == 'loopPlugin':
                edit = TrackEdit(event['type'], event['popcornOptions'])

                self.track_edits.append(edit)

            if event['type'] == 'text' or event['type'] == 'image':
                item = TrackItem(event['type'], event['popcornOptions'])

                item.options['start_stamp'] = \
                    item.options['start']
                item.options['end_stamp'] = \
                    item.options['end']
                item.options['x_px'] = percent_to_px(
                    item.options['left'],
                    self.size[0]
                )
                item.options['y_px'] = percent_to_px(
                    item.options['top'],
                    self.size[1]
                )

                self.track_items.append(item)

            if event['type'] == 'sequencer':
                video = TrackVideo(
                    event['type'],
                    event['popcornOptions']['source'][0],
                    event['popcornOptions']
                )
                self.track_videos.append(video)

        self.parse_duration()

        cfilter = r'color=c={0}:s={1}x{2}:d={3};aevalsrc=0:d={4}'.format(
            self.background_color,
            self.size[0],
            self.size[1],
            self.duration,
            self.duration,
        )
        call(['ffmpeg', '-filter_complex', cfilter, '-y',
              self.current_video.name])
1273309
def libvlc_media_list_new(p_instance):
    '''
    '''
    f = _Cfunctions.get('libvlc_media_list_new', None) or \
        _Cfunction('libvlc_media_list_new', ((1,),), class_result(MediaList),
                    ctypes.c_void_p, Instance)
    return f(p_instance)
691108
def main():
    
    parser = argparse.ArgumentParser()
    parser.add_argument('source_path', help="Path to the video or audio file to subtitle",
                        nargs='?')
    parser.add_argument('-C', '--concurrency', help="Number of concurrent API requests to make",
                        type=int, default=DEFAULT_CONCURRENCY)
    parser.add_argument('-o', '--output',
                        help="Output path for subtitles (by default, subtitles are saved in \
                        the same directory and name as the source path)")
    parser.add_argument('-F', '--format', help="Destination subtitle format",
                        default=DEFAULT_SUBTITLE_FORMAT)
    parser.add_argument('-S', '--src-language', help="Language spoken in source file",
                        default=DEFAULT_SRC_LANGUAGE)
    parser.add_argument('-D', '--dst-language', help="Desired language for the subtitles",
                        default=DEFAULT_DST_LANGUAGE)
    parser.add_argument('-K', '--api-key',
                        help="The Google Translate API key to be used. \
                        (Required for subtitle translation)")
    parser.add_argument('--list-formats', help="List all available subtitle formats",
                        action='store_true')
    parser.add_argument('--list-languages', help="List all available source/destination languages",
                        action='store_true')

    args = parser.parse_args()

    if args.list_formats:
        print("List of formats:")
        for subtitle_format in FORMATTERS:
            print("{format}".format(format=subtitle_format))
        return 0

    if args.list_languages:
        print("List of all languages:")
        for code, language in sorted(LANGUAGE_CODES.items()):
            print("{code}\t{language}".format(code=code, language=language))
        return 0

    if not validate(args):
        return 1

    try:
        subtitle_file_path = generate_subtitles(
            source_path=args.source_path,
            concurrency=args.concurrency,
            src_language=args.src_language,
            dst_language=args.dst_language,
            api_key=args.api_key,
            subtitle_file_format=args.format,
            output=args.output,
        )
        print("Subtitles file created at {}".format(subtitle_file_path))
    except KeyboardInterrupt:
        return 1

    return 0
805409
function TodoViewModel() {
	// GraphQL Queries and Mutations
	var getTodoListQuery = gql`query {
						  todoList {
						    _id
						    task
						    completed
						  }
						}`;
	var removeTodoMutation = gql`mutation removeTodo($_id: ID!) {
					    removeTodo(_id: $_id) {
					        _id
					    }
					}`;
	var createTodoMutation = gql`
		mutation ($task: String!, $completed: Boolean!) {
		  createTodo(task: $task, completed: $completed) {
		    _id
		  }
		}`;
	var updateTodoMutation = gql`
		mutation ($_id: ID!, $task: String!, $completed: Boolean!) {
			updateTodo(_id: $_id, task: $task, completed: $completed) {
			  _id
			  task
			  completed
			}
		}`;
	var graphqlDocumentTodoList = gql`
	  subscription {
        todoList {
          status
          value {
            _id
            task
            completed
          }
        }
      }
    `;

	var self = this;
	var data;

	self.todoList = ko.observableArray().crud({
		constructor: TodoList,
		uniqueIdentifier: "_id"
	}).launchApollo(apolloClient);
	self.todoList.messages = ko.observableArray();

	self.todoList.apollo(
	    {
	        query: getTodoListQuery
	    },
	    {
	        // callback when successful
	        resolve: function(data) {
	        	//initialise with a few Todos because we are very busy people
	        	self.todoList.insert(data.data.todoList);
	        	self.todoList2.insert(data.data.todoList);
	        	self.todoList3.insert(data.data.todoList);
                self.todoList4.insert(data.data.todoList);
	        },
	        // callback to report errors (optional)
	        reject: function(error) {
	            self.call.failMessage("Hey, that didnt work " + error);
	        }
	    }
	);

	self.prepareCollectionEdit = function(data) {
		self.todoList.beforeEdit(ko.toJS(self.todoList()));
		self.todoList.messages([]);
	};

	self.addTask = function() {
		var toSave = {};
		// save new items
		var newInstance = self.todoList.insert(toSave);
		self.todoList.justAdded.push(newInstance);

		var index = self.todoList.indexOf(newInstance);
		self.todoList()[index]._id.isSelected(true);
	};

	self.save = function() {
		/*** Save to server ***/

		// Remove Deleted
		if (self.todoList.justRemoved().length) {
			ko.utils.arrayForEach(self.todoList.justRemoved(), function(item){
				self.todoList.apollo({
					mutation: removeTodoMutation,
					variables: {
						_id: item._id()
					}
				},
				{
					resolve: function(data){
						self.todoList.messages.push({title: "Deleted"}, {content: ko.toJSON(data.data.removeTodo) });
					}
				});
			});
		}

		// Add new tasks
		if (self.todoList.justAdded().length) {
			ko.utils.arrayForEach(self.todoList.justAdded(), function(item){
				self.todoList.apollo({
					mutation: createTodoMutation,
					variables: {
						task: item.task(),
						completed: item.completed()
					}
				},
				{
					resolve: function(data) {
						self.todoList.messages.push({title: "Added"}, {content: ko.toJSON(data.data.createTodo) });
						item._id(data.data.createTodo._id);  // update _id

					}
				});
			});
		}

		var changed = self.todoList.justUpdated();
		if (changed) {
			ko.utils.arrayForEach(changed, function(item){
				self.todoList.apollo({
					mutation: updateTodoMutation,
					variables: {
						_id: item.value._id,
						task: item.value.task,
						completed: item.value.completed
					}
				},
				{
					resolve: function(data) {
						if (data.data.updateTodo) {
							self.todoList.messages.push({title: "Updated ", content: ko.toJSON(data.data.updateTodo)});
						}

					}
				});
			});
		}

		// Knockout
		self.todoList.justRemoved.removeAll(); // empty the parked removed
		self.todoList.justAdded.removeAll(); // empty the parked adds
		self.todoList.beforeEdit(null);
	};

	self.cancel = function() {
		// return model to cache version
		self.todoList.cancelEdit();
		self.todoList.beforeEdit(null);
	};

	self.editItem = function(item) {
		item._id.isSelected(true);
		self.todoList.selectItem(item);
	};

	// Second example
	self.todoList2 = ko.observableArray().crud({
		constructor: TodoList,
		uniqueIdentifier: "_id"
	}).launchApollo(apolloClient);
	self.todoList2.messages = ko.observableArray();
	self.todoList2.loading = true;

	self.addTask2 = function() {
		self.todoList2.itemForAdding(new TodoList({}));
	};

	self.saveAdd = function(data) {
		self.todoList2.insert(ko.toJS(data));
		self.todoList2.itemForAdding(null);
	};

	self.cancelAdd = function() {
		self.todoList2.itemForAdding(null);
	};

	self.todoList2.subscribe(function(v){
		if (self.todoList2.loading) {
			self.todoList2.loading = false;
		} else {
			ko.utils.arrayForEach(v, function(item){
                switch (item.status) {
					case "added":
						self.todoList2.apollo({
							mutation: createTodoMutation,
							variables: {
								task: item.value.task.peek(),
								completed: item.value.completed.peek()
							}
						},
						{
							resolve: function(data) {
								self.todoList2.messages.push({title: "Added"}, {content: ko.toJSON(data.data.createTodo) });
								item.value._id(data.data.createTodo._id);  // update _id
							}
						});
						break;
					case "deleted":
						self.todoList2.apollo({
							mutation: removeTodoMutation,
							variables: {
								_id: item.value._id.peek()
							}
						},
						{
							resolve: function(data){
								self.todoList2.messages.push({title: "Deleted"}, {content: ko.toJSON(data.data.removeTodo) });
							}
						});
						break;
					case "updated":
						self.todoList2.apollo({
							mutation: updateTodoMutation,
							variables: {
								_id: item.value._id.peek(),
								task: item.value.task.peek(),
								completed: item.value.completed.peek()
							}
						},
						{
							resolve: function(data) {
								if (data.data.updateTodo) {
									self.todoList2.messages.push({title: "Updated ", content: ko.toJSON(data.data.updateTodo)});
								}

							}
						});
						break;
				}
			});
		}
	}, null, "arrayChange");


	// Third example - watch via a Subscription to the Server
	self.todoList3 = ko.observableArray().crud({
		constructor: TodoList,
		uniqueIdentifier: "_id"
	}).liftOffSubscription(apolloClient);

	self.todoList3.startGraphqlSubscription(
		{
			query: graphqlDocumentTodoList,
		},
		{
			next: function(data) {
				switch (data.data.todoList.status) {
    	        	case "added":
    	        		self.todoList3.insert(data.data.todoList.value);
    	        		break;
    	        	case "updated":
    	        		self.todoList3.upsert(data.data.todoList.value);
    	        		break;
    	        	case "deleted":
    	        		var _id = data.data.todoList.value._id;
    	        		var exists = ko.utils.arrayFirst(self.todoList3.peek(), function(item) {
    						return ko.unwrap(item._id) === _id;
    					});
    					if (exists) {
    	        			self.todoList3.remove(exists);
    					}
    	        		break;
    	        }
			}
		}
	);


    // Fourth example - Optimistic updates
    self.todoList4 = ko.observableArray().crud({
        constructor: TodoList,
        uniqueIdentifier: "_id"
    }).launchApollo(apolloClient);

    self.todoList4.messages = ko.observableArray();
    self.todoList4.loading = true;

    self.addTask4 = function() {
        self.todoList4.itemForAdding(new TodoList({}));
    };

    self.saveAdd4 = function(v) {
        let item = self.todoList4.insert(ko.toJS(v));
        self.todoList4.itemForAdding(null);

        // contact server
        self.todoList4.apollo({
            mutation: createTodoMutation,
            variables: {
                task: item.task.peek(),
                completed: item.completed.peek()
            },
            // optimistic part
            optimisticResponse: function(data){
                data = Object.assign({_id: Math.round(Math.random() * -1000000)}, data);
                data.__typename = 'TodoList';
                return {
                    createTodo: {
                        _id: data._id,
                        todoList: data,
                        __typename: 'TodoList'
                    }
                };
            },
            update: function(cache, {data: {createTodo}}) {
                // Read the data from our cache for this query.
                const data = cache.readQuery({ query: getTodoListQuery });

                if (createTodo._id < 0) {
                    // Optimistic data goes into cache
                    data.todoList.push(createTodo.todoList);
                } else {
                    // _id returned from server so push again
                    data.todoList.push(
                        {
                            _id: createTodo._id,
                            task: item.task.peek(),
                            completed: item.completed.peek(),
                            __typename: createTodo.__typename
                        }
                    );

                    item._id(createTodo._id);  // update _id in knockout
                }

                // Write our data back to the cache.
                cache.writeQuery({ query: getTodoListQuery, data });
            }
            // close optimistic update
        },
        {
            resolve: function(data) {
                self.todoList4.messages.push({title: "Added"}, {content: ko.toJSON(data.data.createTodo) });
            }
        });

    };

    self.cancelAdd4 = function() {
        self.todoList4.itemForAdding(null);
    };

    self.deleteItem4 = function(item) {
        let index = self.todoList4.indexOf(item);
        self.todoList4.remove(item);

        // contact server
        self.todoList4.apollo({
            mutation: removeTodoMutation,
            variables: {
                _id: item._id.peek()
            },
            // optimistic part
            optimisticResponse: function(data){
                data.__typename = 'TodoList';
                return {
                    removeTodo: {
                        _id: data._id,
                        todoList: data,
                        __typename: 'TodoList'
                    }
                };
            },
            update: function(cache, {data: {removeTodo}}) {
                // Read the data from our cache for this query.
                const data = cache.readQuery({ query: getTodoListQuery });

                // remove from store
                ko.utils.arrayRemoveItem(
                    data.todoList,
                    ko.utils.arrayFirst(data.todoList, function(obj){
                        return obj._id === removeTodo._id;
                    })
                );

                // Write our data back to the cache.
                cache.writeQuery({ query: getTodoListQuery, data });
            }
            // close optimistic update
        },
        {
            resolve: function(data){
                self.todoList4.messages.push({title: "Deleted"}, {content: ko.toJSON(data.data.removeTodo) });
            },
            reject: function(error) {
                self.todoList4.apollo.failMessage("Hey, that didnt work " + error);
                alert("hey, that didnt work. Error: " + error + ".  Will need to revert to previous state");

                self.todoList4.splice(index, 0, item);
            }
        });
    };

    /**
     * Provide a clean object for saving
     * @param  {object} item object with update function
     * @return {object} return object
     */
    let cleanItem = function(item) {
        item = ko.toJS(item);
        delete item.update; // remove method
        return item;
    };

    self.acceptEditItem4 = function(item) {
        let selected = self.todoList4.selectedItem(); // obtain "this"
        let originalItem = ko.toJS(self.todoList4.selectedItem.peek());

        //apply updates from the edited item to the selected item
        selected.update(cleanItem(item));

        //clear editing values
        self.todoList4.selectedItem(null);
        self.todoList4.itemForEditing(null);

        // Communicate with server
        self.todoList4.apollo({
            mutation: updateTodoMutation,
            variables: {
                _id: item._id.peek(),
                task: item.task.peek(),
                completed: item.completed.peek()
            },
            // optimistic part
            optimisticResponse: function(data){
                data.__typename = 'TodoList';
                return {
                    updateTodo: {
                        _id: data._id,
                        task: data.task,
                        completed: data.completed,
                        __typename: 'TodoList'
                    }
                };
            }
            // close optimistic update (no need for update as is automatic)
        },
        {
            resolve: function(data) {
                if (data.data.updateTodo) {
                    self.todoList4.messages.push({title: "Updated ", content: ko.toJSON(data.data.updateTodo)});
                }

            },
            reject: function(error) {
                self.todoList4.apollo.failMessage("Hey, that didnt work " + error);
                alert("hey, that didnt work. Error: " + error + ".  Will need to revert to previous state");

                selected.update(cleanItem(originalItem));
            }
        });
    };




	//  Vanilla subscription
/*	apolloClient.subscribe({
	    query: graphqlDocumentTodoList
	}).subscribe({
	    next (data) {
	        // Notify your application with the new arrived data
            console.log("got to Vanilla subscription");
            console.log(data);
	    }
	}); */
}